from ..waveguides.waveguide_traces import WG_TMPL
import ipkiss3.all as i3
from ipkiss.technology import get_technology

TECH = get_technology()


class _LinearEdgeTaper(i3.PCell):
    _name_prefix = "LinearEdgeTaper"
    _doc_properties = []

    # Call trace template
    trace_template = i3.TraceTemplateProperty(doc="Template of the waveguide", locked=True)

    def _default_trace_template(self):
        return WG_TMPL(name=self.name + "_tt")

    class Layout(i3.LayoutView):
        _doc_properties = [
            "square_width",
            "taper_length_fixed_width",
            "taper_length",
            "taper_edge_width",
            "taper_end_width",
        ]
        square_width = i3.PositiveNumberProperty(
            default=5.0,
            doc="Width of the square box holding edge of taper section.",
        )
        taper_length_fixed_width = i3.PositiveNumberProperty(default=200, doc="Length of fixed taper edge width.")
        taper_length = i3.PositiveNumberProperty(default=1500, doc="Taper length.")
        taper_edge_width = i3.PositiveNumberProperty(default=0.130, doc="Edge taper width.")
        taper_end_width = i3.PositiveNumberProperty(default=0.80, doc="Edge end width.")

        def _generate_elements(self, elems):
            square_width = self.square_width
            taper_length_fixed_width = self.taper_length_fixed_width
            taper_length = self.taper_length
            taper_edge_width = self.taper_edge_width
            taper_end_width = self.taper_end_width
            core_layer = self.trace_template.core_layer

            # Draw box that holds taper edge
            elems += i3.Rectangle(
                layer=core_layer,
                center=(0.5 * square_width, 0),
                box_size=(square_width, square_width),
            )

            # Draw section of fixed taper width
            elems += i3.Line(
                layer=core_layer,
                begin_coord=(square_width, 0),
                end_coord=(square_width + taper_length_fixed_width, 0),
                line_width=taper_edge_width,
            )

            # Draw taper
            elems += i3.Wedge(
                layer=core_layer,
                begin_coord=(square_width + taper_length_fixed_width, 0),
                end_coord=(square_width + taper_length_fixed_width + taper_length, 0),
                begin_width=taper_edge_width,
                end_width=taper_end_width,
            )

            return elems

        def _generate_ports(self, ports):  # we place the ports in the same way as the tapers
            square_width = self.square_width
            taper_length_fixed_width = self.taper_length_fixed_width
            taper_length = self.taper_length
            tt = self.trace_template
            tt.set(core_width=self.taper_end_width)

            ports += i3.VerticalOpticalPort(name="in0", position=(0, 0), angle=0)

            ports += i3.OpticalPort(
                name="out0",
                position=(square_width + taper_length_fixed_width + taper_length, 0),
                angle=0,
                trace_template=tt,
            )

            return ports


class LinearEdgeTaperPCell(_LinearEdgeTaper):
    """
    Linear tapered waveguide for edge coupling.
    """

    _name_prefix = "EdgeTaper"
