import gdsfactory as gf

from cnmpdk.config import PATH

import gdsfactory as gf
from pydantic import BaseModel
from gdsfactory.typings import Layer
from functools import partial
from gdsfactory.technology import LayerLevel, LayerStack, LayerMap
from gdsfactory.cross_section import cross_section

class LayerMapFab(LayerMap):
    SHALLOW_WAVEGUIDES: Layer = (1, 0)
    DEEP_WAVEGUIDES: Layer = (2, 0)
    TRENCH: Layer = (3, 0)
    HEATER: Layer = (4, 0)
    DEEP_WAVEGUIDES_PROTECTION: Layer = (11, 0)
    SHALLOW_WAVEGUIDES_PROTECTION: Layer = (21, 0)
    DICING_LINES: Layer = (100, 0)
    PORT: Layer = (1,10)
    BB_OUTLINE: Layer = (51,0)
    BB_GUIDES: Layer = (52,0)
    BB_PARAMETERS: Layer = (53,0)
    
LAYER = LayerMapFab

# Define XSections
deep = gf.partial(
    gf.cross_section.strip,
    width=1.2,
    radius=100,
    layer=LAYER.DEEP_WAVEGUIDES,
    cladding_layers=[LAYER.DEEP_WAVEGUIDES, LAYER.DEEP_WAVEGUIDES_PROTECTION],
    cladding_offsets=[0, 15],
)
shallow = gf.partial(
    gf.cross_section.strip,
    width=1.2,
    radius=150,
    layer=LAYER.SHALLOW_WAVEGUIDES,
    cladding_layers=[LAYER.SHALLOW_WAVEGUIDES,LAYER.SHALLOW_WAVEGUIDES_PROTECTION],
    cladding_offsets=[0, 15],
)
heater = gf.partial(
    cross_section,
    width=10,
    layer=LAYER.HEATER,
)
trench = gf.partial(
    cross_section,
    width=10,
    layer=LAYER.TRENCH,
)

cnm_cross_sections = dict( cnm_deep=deep, cnm_trench=trench, cnm_heater=heater, cnm_shallow=shallow)

nm = 1e-3
um = 1

def get_layer_stack_cnmpdk(
    Thermal_SiO2_thickness: float = -2.5*um,
    zmin_Thermal_SiO2: float = -2.5*um,

    LPCVD_Si3N4_thickness: float = 300 * nm,
    zmin_LPCVD_Si3N4: float = 0.0,

    PECVD_SiO2_thickness: float = -2*um,
    zmin_PECVD_SiO2: float = 300*nm,

    thickness_Cr: float = 10 * nm,
    zmin_Cr: float = 300*nm + 2*um,

    thickness_Au: float = 90*nm,
    zmin_Au: float = 300*nm + 2*um + 90*nm,
) -> LayerStack:
    """Returns cnmpdk LayerStack"""

    return LayerStack(
        layers=dict(
            # TODO: Add Wafer Substrate
            # substrate=LayerLevel(
            #     layer=LAYER.DICING_LINES,
            #     thickness=substrate_thickness,
            #     zmin=-substrate_thickness - box_thickness,
            #     material="Si",
            #     mesh_order=101,
            #     background_doping={"concentration": "1E14", "ion": "Boron"},
            #     orientation="100",
            # ),
            box=LayerLevel(
                layer=LAYER.DICING_LINES,
                thickness=Thermal_SiO2_thickness,
                zmin=zmin_Thermal_SiO2,
                material="SiO2",
                mesh_order=9,
            ),

            wg=LayerLevel(
                layer=LAYER.DEEP_WAVEGUIDES,
                thickness=LPCVD_Si3N4_thickness,
                zmin=0,
                material="SiN",
            ),

            metal1=LayerLevel(
                layer=LAYER.HEATER,
                thickness=thickness_Cr,
                zmin=zmin_Cr,
                material="Cr",
                mesh_order=2,
            ),
            metal2=LayerLevel(
                layer=LAYER.HEATER,
                thickness=thickness_Au,
                zmin=zmin_Au,
                material="Au",
                mesh_order=2,
            ),
        )
    )
               

LAYER_STACK = get_layer_stack_cnmpdk()