import pya
from pya import *
from SiEPIC.utils import get_technology_by_name


class Waveguide_SWG_Assist(pya.PCellDeclarationHelper):
    """
    Input: length, target_period, wg_width, width, duty
    """

    def __init__(self):
        # Important: initialize the super class
        super(Waveguide_SWG_Assist, self).__init__()
        TECHNOLOGY = get_technology_by_name("EBeam")

        # declare the parameters
        self.param("length", self.TypeDouble, "Waveguide length", default=10.0)
        self.param(
            "target_period", self.TypeDouble, "Target period (microns)", default=0.200
        )
        self.param("swg_wg_width", self.TypeDouble, "SWG Waveguide width", default=0.5)
        self.param(
            "strip_wg_width", self.TypeDouble, "Strip Waveguide width", default=0.06
        )
        self.param("duty", self.TypeDouble, "Duty Cycle (0 to 1)", default=0.5)
        self.param("layer", self.TypeLayer, "Layer", default=TECHNOLOGY["Si"])
        self.param(
            "pinrec", self.TypeLayer, "PinRec Layer", default=TECHNOLOGY["PinRec"]
        )
        self.param(
            "devrec", self.TypeLayer, "DevRec Layer", default=TECHNOLOGY["DevRec"]
        )

    #    self.param("textl", self.TypeLayer, "Text Layer", default = LayerInfo(10, 0))

    def display_text_impl(self):
        # Provide a descriptive text for the cell
        return "Waveguide_SWG_Assist_%s-%.3f-%.3f-%.3f-%.3f" % (
            self.length,
            self.target_period,
            self.swg_wg_width,
            self.strip_wg_width,
            self.duty,
        )

    def coerce_parameters_impl(self):
        pass

    def can_create_from_shape(self, layout, shape, layer):
        return False

    def produce_impl(self):
        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes

        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        # LayerSiSPN = ly.layer(LayerSiSP)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        # Determine the period such that the waveguide length is as desired.  Slight adjustment to period
        N_boxes = int(round(self.length / self.target_period - 0.5))
        grating_period = self.length / (N_boxes) / dbu
        # print("N boxes: %s, grating_period: %s" % (N_boxes, grating_period) )

        # Draw the Bragg grating:
        box_width = int(round(grating_period * self.duty))

        w = self.swg_wg_width / dbu
        half_w = w / 2
        for i in range(0, N_boxes + 1):
            x = int(round((i * grating_period - box_width / 2)))
            box1 = Box(x, -half_w, x + box_width, half_w)
            shapes(LayerSiN).insert(box1)
        length = self.length / dbu

        # Strip waveguide:
        w_strip = self.strip_wg_width / dbu
        if w_strip > 0:
            box1 = Box(0, -w_strip / 2, length, w_strip / 2)
            shapes(LayerSiN).insert(box1)

        # Pins on the waveguide:
        from SiEPIC._globals import PIN_LENGTH as pin_length

        #    pin_length = box_width
        t = Trans(Trans.R0, 0, 0)
        pin = Path([Point(pin_length / 2, 0), Point(-pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        t = Trans(Trans.R0, length, 0)
        pin = Path([Point(-pin_length / 2, 0), Point(pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin2", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_halign = 2
        shape.text_size = 0.4 / dbu

        # Compact model information
        t = Trans(Trans.R0, 0, 0)
        text = Text("Lumerical_INTERCONNECT_library=Design kits/ebeam", t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, length / 10, 0)
        text = Text("Component=NO_MODEL_AVAILABLE", t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, length / 9, -box_width * 2)
        text = Text(
            "Spice_param:length=%.3fu target_period=%.3fu grating_period=%.3fu swg_wg_width=%.3fu strip_wg_width=%.3fu duty=%.3f "
            % (
                self.length,
                self.target_period,
                round(grating_period) * dbu,
                self.swg_wg_width,
                self.strip_wg_width,
                self.duty,
            ),
            t,
        )
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        points = [pya.Point(0, 0), pya.Point(length, 0)]
        path = pya.Path(points, w)
        path = pya.Path(points, w * 3)
        shapes(LayerDevRecN).insert(path.simple_polygon())
