####################################################################
# VIRTUAL FABRICATION
####################################################################
from ipkiss.plugins.vfabrication.process_flow import VFabricationProcessFlow
from ipkiss.technology import get_technology
from ipkiss.technology.technology import TechnologyTree
from pysics.basics.material.material import Material, MaterialFactory
from pysics.basics.material.material_stack import MaterialStack, MaterialStackFactory
from ipkiss.visualisation.display_style import DisplayStyle
from ipkiss.visualisation import color
from pysics.basics.environment import Environment

TECH = get_technology()

###############
# CUSTOM COLORS
###############
COLOR_BABY_BLUE = color.Color(name="Baby blue", red=0.78, green=0.84, blue=0.91)
COLOR_UGLY_PINK = color.Color(name="Ugly pink", red=0.82, green=0.59, blue=0.58)
COLOR_DARK_UGLY_PINK = color.Color(name="Dark ugly pink", red=0.63, green=0.43, blue=0.43)
COLOR_LIGHT_UGLY_PINK = color.Color(name="Ligtht ugly pink", red=0.90, green=0.76, blue=0.76)
COLOR_DIAPER_BLUE = color.Color(name="Diaper blue", red=0.58, green=0.70, blue=0.84)
COLOR_COPPER_BROWN = color.Color(name="Copper Brown", red=200.0 / 255.0, green=117.0 / 255.0, blue=51.0 / 255.0)
COLOR_AL_GRAY = color.Color(name="Aluminum Gray", red=173.0 / 255, green=178.0 / 255, blue=189.0 / 255)
COLOR_LIGHT_BLUE = color.Color(name="Lightblue", red=0.4, green=0.4, blue=0.9)
COLOR_DARK_BLUE = color.Color(name="Darkblue", red=0.0, green=0.0, blue=0.4)
COLOR_LIGHT_RED = color.Color(name="Lightred", red=0.9, green=0.4, blue=0.4)
COLOR_DARK_RED = color.Color(name="Darkred", red=0.4, green=0.0, blue=0.0)
COLOR_TUNGSTEN = color.Color(name="Tungsten", red=0.47, green=0.49, blue=0.52)
COLOR_PRETTY_PURPLE = color.Color(name="Pretty purple", red=0.3, green=0.00, blue=0.6)
COLOR_LIGHT_PRETTY_PURPLE = color.Color(name="Light Pretty purple", red=0.6, green=0.2, blue=1)
COLOR_YELLOW = color.Color(name="Yellow", red=1, green=1, blue=0)
COLOR_GHOST_WHITE = color.Color(name="White", red=248 / 255, green=248 / 255, blue=1)


####################################################################
# MATERIALS
####################################################################
TECH.MATERIALS = MaterialFactory()
TECH.MATERIALS.AIR = Material(name="air", display_style=DisplayStyle(color=COLOR_GHOST_WHITE), solid=False)
TECH.MATERIALS.THERMAL_OXIDE = Material(name="Thermal oxide", display_style=DisplayStyle(color=COLOR_DIAPER_BLUE))
TECH.MATERIALS.SILICON_OXIDE = Material(
    name="silicon oxide Cladding",
    display_style=DisplayStyle(color=COLOR_BABY_BLUE),
)
TECH.MATERIALS.AL2O3 = Material(name="Al2O3", display_style=DisplayStyle(color=COLOR_UGLY_PINK))
TECH.MATERIALS.CHROMIUM = Material(name="Chromium", display_style=DisplayStyle(color=COLOR_AL_GRAY))
TECH.MATERIALS.PLATINUM = Material(name="Platinum", display_style=DisplayStyle(color=COLOR_COPPER_BROWN))
TECH.MATERIALS.GOLD = Material(name="Gold", display_style=DisplayStyle(color=COLOR_YELLOW))


def al2o3_eps_model(env):
    # Sellmeier Parameters are provided : B = 2.825 C = 0.00727
    w = env.wavelength  # wavelength in nm
    B = 2.825
    C = 0.00727
    return 1 + (B * w**2) / (w**2 - C)


def tox_eps_model(env):
    # Sellmeier Parameters are provided : B = 1.452 C = 0.00250
    w = env.wavelength  # wavelength in nm
    B = 1.452
    C = 0.00250
    return 1 + (B * w**2) / (w**2 - C)


def sio2_eps_model(env):
    # Sellmeier Parameters are provided : B = 1.446 C = 0.00253
    w = env.wavelength  # wavelength in nm
    B = 1.446
    C = 0.00253
    return 1 + (B * w**2) / (w**2 - C)


TECH.MATERIALS.AL2O3.get_epsilon = al2o3_eps_model
TECH.MATERIALS.THERMAL_OXIDE.get_epsilon = tox_eps_model
TECH.MATERIALS.SILICON_OXIDE.get_epsilon = sio2_eps_model
TECH.MATERIALS.AIR.epsilon = 1

TECH.MATERIALS.AL2O3.epsilon = TECH.MATERIALS.AL2O3.get_epsilon(Environment(wavelength=1.55)).real
TECH.MATERIALS.THERMAL_OXIDE.epsilon = TECH.MATERIALS.THERMAL_OXIDE.get_epsilon(Environment(wavelength=1.55)).real
TECH.MATERIALS.SILICON_OXIDE.epsilon = TECH.MATERIALS.SILICON_OXIDE.get_epsilon(Environment(wavelength=1.55)).real

# Material stacks
TECH.MATERIAL_STACKS = MaterialStackFactory()

MSTACK_TOX_HEIGHT = 8.0
MSTACK_AL2O3_HEIGHT = 0.062
MSTACK_CLAD_HEIGHT = 8.0
MSTACK_CR_HEIGHT = 0.01
MSTACK_PT_HEIGHT = 0.01
MSTACK_AU_HEIGHT = 0.3
MSTACK_METAL_HEIGHT = MSTACK_CR_HEIGHT + MSTACK_PT_HEIGHT + MSTACK_AU_HEIGHT

TECH.VFABRICATION = TechnologyTree()

TECH.MATERIAL_STACKS.MSTACK_OX = MaterialStack(
    name="Oxide",
    materials_heights=[
        (TECH.MATERIALS.THERMAL_OXIDE, MSTACK_TOX_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_AL2O3_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CLAD_HEIGHT),
        (TECH.MATERIALS.AIR, MSTACK_METAL_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_BLUE),
)
TECH.MATERIAL_STACKS.MSTACK_ALO = MaterialStack(
    name="Aluminium Oxide",
    materials_heights=[
        (TECH.MATERIALS.THERMAL_OXIDE, MSTACK_TOX_HEIGHT),
        (TECH.MATERIALS.AL2O3, MSTACK_AL2O3_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CLAD_HEIGHT),
        (TECH.MATERIALS.AIR, MSTACK_METAL_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_DARK_GREEN),
)
TECH.MATERIAL_STACKS.MSTACK_ALO_M1 = MaterialStack(
    name="Aluminium Oxide + Metal1",
    materials_heights=[
        (TECH.MATERIALS.THERMAL_OXIDE, MSTACK_TOX_HEIGHT),
        (TECH.MATERIALS.AL2O3, MSTACK_AL2O3_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CLAD_HEIGHT),
        (TECH.MATERIALS.CHROMIUM, MSTACK_CR_HEIGHT),
        (TECH.MATERIALS.PLATINUM, MSTACK_PT_HEIGHT),
        (TECH.MATERIALS.GOLD, MSTACK_AU_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_TITANIUM_YELLOW),
)
TECH.MATERIAL_STACKS.MSTACK_ALO_HT = MaterialStack(
    name="Aluminium Oxide + Heater",
    materials_heights=[
        (TECH.MATERIALS.THERMAL_OXIDE, MSTACK_TOX_HEIGHT),
        (TECH.MATERIALS.AL2O3, MSTACK_AL2O3_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CLAD_HEIGHT),
        (TECH.MATERIALS.CHROMIUM, MSTACK_CR_HEIGHT),
        (TECH.MATERIALS.PLATINUM, MSTACK_PT_HEIGHT),
        (TECH.MATERIALS.AIR, MSTACK_AU_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_MAGENTA),
)
TECH.MATERIAL_STACKS.MSTACK_M1 = MaterialStack(
    name="Metal1",
    materials_heights=[
        (TECH.MATERIALS.THERMAL_OXIDE, MSTACK_TOX_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_AL2O3_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CLAD_HEIGHT),
        (TECH.MATERIALS.CHROMIUM, MSTACK_CR_HEIGHT),
        (TECH.MATERIALS.PLATINUM, MSTACK_PT_HEIGHT),
        (TECH.MATERIALS.GOLD, MSTACK_AU_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_YELLOW),
)
TECH.MATERIAL_STACKS.MSTACK_HT = MaterialStack(
    name="Heater",
    materials_heights=[
        (TECH.MATERIALS.THERMAL_OXIDE, MSTACK_TOX_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_AL2O3_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CLAD_HEIGHT),
        (TECH.MATERIALS.CHROMIUM, MSTACK_CR_HEIGHT),
        (TECH.MATERIALS.PLATINUM, MSTACK_PT_HEIGHT),
        (TECH.MATERIALS.AIR, MSTACK_AU_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_RED),
)

# Process in the Al2O3 layer
TECH.VFABRICATION.PROCESS_FLOW_FEOL = VFabricationProcessFlow(
    active_processes=[
        TECH.PROCESS.WG,
        TECH.PROCESS.M1,
        TECH.PROCESS.HEATER,
    ],
    # DO NOT CHANGE THE SEQUENCE OF THE ELEMENTS !
    # IT MUST MATCH THE SEQUENCE OF THE COLUMNS IN VFABRICATION PROPERTY process_to_material_stack_map
    process_layer_map={
        TECH.PROCESS.WG: TECH.PPLAYER.WG,
        TECH.PROCESS.M1: TECH.PPLAYER.M1,
        TECH.PROCESS.HEATER: TECH.PPLAYER.HEATER,
    },
    process_to_material_stack_map=[
        # WG, M1, HEATER
        ((0, 0, 0), TECH.MATERIAL_STACKS.MSTACK_OX),
        ((1, 0, 0), TECH.MATERIAL_STACKS.MSTACK_ALO),
        ((0, 1, 0), TECH.MATERIAL_STACKS.MSTACK_M1),
        ((1, 1, 0), TECH.MATERIAL_STACKS.MSTACK_ALO_M1),
        ((0, 0, 1), TECH.MATERIAL_STACKS.MSTACK_HT),
        ((0, 1, 1), TECH.MATERIAL_STACKS.MSTACK_HT),
        ((1, 0, 1), TECH.MATERIAL_STACKS.MSTACK_ALO_HT),
        ((1, 1, 1), TECH.MATERIAL_STACKS.MSTACK_ALO_HT),
    ],
    is_lf_fabrication={
        TECH.PROCESS.WG: False,
        TECH.PROCESS.M1: False,
        TECH.PROCESS.HEATER: False,
    },
)


TECH.VFABRICATION.PROCESS_FLOW = TECH.VFABRICATION.PROCESS_FLOW_FEOL
