"""Registering a layer transition.

When a route's port_a and port_b live on different layers, the router
consults a `TransitionRegistry`. If the layer pair has a registered
factory, the router drops in the resulting PCell automatically. Here
we wire SILC ↔ SILN with the built-in `PhotonicElevator`.
"""
import lumicron as lm
import lumicron_pdk as lpdk

LAYER = lpdk.LayerTable(
    SILC = lpdk.Layer(9, 0, color="#008000", min_width=0.2, min_radius=5.0),
    SILN = lpdk.Layer(5, 0, color="#ff69b4", min_width=0.4, min_radius=10.0),
    OXOP = lpdk.Layer(17, 0, color="#d4a574"),
)


@lpdk.route_profile(port_width=0.5, radius=10.0, radius_min=5.0)
def silc_strip(p):
    p.layer(LAYER.SILC, width=p.port_width)


@lpdk.route_profile(port_width=0.5, radius=10.0, radius_min=5.0)
def siln_strip(p):
    p.layer(LAYER.SILN, width=p.port_width)


def silc_siln_elevator():
    """Factory: returns a fresh SILC ↔ SILN elevator each call.

    The router calls this every time a route needs the transition,
    so the registry stores the function rather than a cached cell.
    """
    return lpdk.PhotonicElevator(
        layer_a=LAYER.SILC, layer_b=LAYER.SILN,
        width_a=0.5, width_b=0.5,
        tip_a=0.08, tip_b=0.08,
        taper_length_a=25.0, taper_length_b=25.0,
        overlap=10.0,
        cladding_layer=LAYER.OXOP, cladding_margin=2.0,
        route_profile_a=silc_strip,
        route_profile_b=siln_strip,
    )


# Register both into a PDK-local registry and into the process-wide
# default registry, so end-user scripts get auto-transitions just by
# importing the PDK.
TRANSITIONS = lpdk.TransitionRegistry()
TRANSITIONS.register(LAYER.SILC, LAYER.SILN, silc_siln_elevator)
lpdk.default_transitions().register(LAYER.SILC, LAYER.SILN, silc_siln_elevator)


@lm.pcell
def TransitionDemo():
    """A route whose endpoints are on different layers — the registered
    elevator drops in automatically."""
    c = lm.CELL("TransitionDemo")
    c.add(lm.PORT("in",  position=(0, 0),   direction=0,
                  route_profile=silc_strip))
    c.add(lm.PORT("out", position=(600, 0), direction=180,
                  route_profile=siln_strip))
    c.Route(c.ports["in"], c.ports["out"], transition_offset=300)
    return c


if __name__ == "__main__":
    TransitionDemo().to_gds("transition_demo.gds")
