"""Route — route N parallel channels with one call.

Three modes, picked by what you pass:

    - `Route(...)` (default style)            → direct: per-channel,
                                                       no coordination.
    - `Route(..., style="manhattan")`         → auto-spined manhattan
                                                       bundle; the router
                                                       picks the shortest
                                                       path from ports_a's
                                                       centroid to ports_b's.
    - `Route(...).go("E", by=...)`            → manhattan-spined too,
                                                       but you steer the
                                                       spine leg by leg.

This example uses the auto-spined form, which is the right default when
your bundle just needs to "go from A to B."
"""
import lumicron as lm
import lumicron.pdks.elyon_demo.all as pdk


@lm.pcell
def BundleDemo(n: int = 4, pitch: float = 40.0, span: float = 600.0,
               y_shift: float = 200.0):
    c = lm.CELL("BundleDemo")

    for i in range(n):
        y = i * pitch
        c.add(lm.PORT(
            f"in{i}", position=(0, y), direction=0,
            route_profile=pdk.RP.silc_strip,
        ))
        c.add(lm.PORT(
            f"out{i}", position=(span, y + y_shift), direction=180,
            route_profile=pdk.RP.silc_strip,
        ))

    ports_a = [c.ports[f"in{i}"] for i in range(n)]
    ports_b = [c.ports[f"out{i}"] for i in range(n)]
    c.Route(ports_a, spacing=pitch, radius=15,
                  style="manhattan").to(ports_b)
    return c


if __name__ == "__main__":
    BundleDemo().to_gds("bundle_demo.gds")
