#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 
# Copyright 2019-2021 SkyWater PDK Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This code is *alternatively* available under a BSD-3-Clause license, see
# details in the README.md at the top level and the license text at
# https://github.com/google/skywater-pdk-libs-sky130_bag3_pr/blob/master/LICENSE.alternative
#
# SPDX-License-Identifier: BSD-3-Clause OR Apache 2.0


from typing import Tuple, Optional, Mapping

from pybag.core import BBox

from bag.util.immutable import Param
from bag.layout.tech import TechInfo
from bag.layout.template import TemplateBase

from xbase.layout.enum import DeviceType

from . import config as _config
from . import config_fname as _config_fname
from .mos.tech import MOSTechSkywater130
from .mim.tech import MIMTechSkywater130
# from .fill.tech import FillTechSkywater130
from .res.tech import ResTechSkywater130


class TechInfoSkywater130(TechInfo):
    def __init__(self, process_params):
        TechInfo.__init__(self, process_params, _config, _config_fname)

        self.register_device_tech('mos', MOSTechSkywater130)
        self.register_device_tech('mim', MIMTechSkywater130)
        self.register_device_tech('res', ResTechSkywater130)
        # self.register_device_tech('fill', FillTechSkywater130)

    def get_margin(self, is_vertical: bool, edge1: Param, edge2: Optional[Param]) -> int:
        if edge2 is None:
            dev_type = edge1['dev_type']
            if dev_type is DeviceType.MOS:
                margins: Mapping[str, int] = edge1['margins']
                table: Mapping[str, Tuple[int, int]] = self.config['margins']
                max_sp = 0
                for name, val in margins.items():
                    sp_tot = -(-table[name][is_vertical] // 2)
                    max_sp = max(sp_tot - val, max_sp)
                return max_sp
            else:
                # TODO: implement this
                raise ValueError('Not implemented yet, see developer.')
        else:
            # TODO: implement this
            raise ValueError('Not implemented yet, see developer.')

    def add_cell_boundary(self, template: TemplateBase, box: BBox) -> None:
        if box.is_physical():
            pt_list = [(box.xl, box.yl), (box.xl, box.yh), (box.xh, box.yh), (box.xh, box.yl)]
            # template.add_boundary(BoundaryType.PR, pt_list)

    def draw_device_blockage(self, template: TemplateBase) -> None:
        pass

    def get_metal_em_specs(self, layer: str, purpose: str, w: int, length: int = -1,
                           vertical: bool = False, dc_temp: int = -1000, rms_dt: int = -1000
                           ) -> Tuple[float, float, float]:
        idc = self._get_metal_idc(layer, purpose, w, length, vertical, dc_temp)
        irms = self._get_metal_irms(layer, purpose, w, rms_dt)
        ipeak = float('inf')
        return idc, irms, ipeak

    def get_via_em_specs(self, layer_dir: int, layer: str, purpose: str, adj_layer: str,
                         adj_purpose: str, cut_w: int, cut_h: int, m_w: int = -1, m_l: int = -1,
                         adj_m_w: int = -1, adj_m_l: int = -1, array: bool = False,
                         dc_temp: int = -1000, rms_dt: int = -1000) -> Tuple[float, float, float]:
        def_purpose = self.default_purpose
        purpose = purpose or def_purpose
        adj_purpose = adj_purpose or def_purpose

        lay_vec = [None, None]
        dim_vec = [None, None]

        lay_vec[layer_dir] = (layer, purpose)
        lay_vec[1 - layer_dir] = (adj_layer, adj_purpose)
        dim_vec[layer_dir] = (m_w, m_l)
        dim_vec[1 - layer_dir] = (adj_m_w, adj_m_l)

        idc = self._get_via_idc(lay_vec[0], lay_vec[1], cut_w, cut_h, dim_vec[0], dim_vec[1],
                                array, dc_temp)
        # via do not have AC current specs
        irms = float('inf')
        ipeak = float('inf')
        return idc, irms, ipeak

    def get_res_em_specs(self, res_type: str, w: int, *, length: int = -1,
                         dc_temp: int = -1000, rms_dt: int = -1000) -> Tuple[float, float, float]:
        dc_temp = self.get_dc_temp(dc_temp)
        rms_dt = self.get_rms_dt(rms_dt)

        idc_scale = self.get_idc_scale_factor('', '', dc_temp, is_res=True)
        idc = 1.0e-3 * w * idc_scale

        irms = 1e-3 * (0.02 * rms_dt * w * (w + 0.5)) ** 0.5

        ipeak = 5e-3 * 2 * w
        return idc, irms, ipeak

    # noinspection PyUnusedLocal,PyMethodMayBeStatic
    def _get_metal_idc_factor(self, layer: str, purpose: str, w: int, length: int):
        return 1

    def _get_metal_idc(self, layer: str, purpose: str, w: int, length: int,
                       vertical: bool, dc_temp: int) -> float:
        if vertical:
            raise NotImplementedError('Vertical DC current not supported yet')

        inorm, woff = 1.0, 0.0
        idc = inorm * self._get_metal_idc_factor(layer, purpose, w, length) * (w - woff)
        return self.get_idc_scale_factor(layer, purpose, self.get_dc_temp(dc_temp)) * idc * 1e-3

    # noinspection PyUnusedLocal
    def _get_metal_irms(self, layer: str, purpose: str, w: int, rms_dt: int):
        b = 0.0443
        k, wo, a = 6.0, 0.0, 0.2

        irms_ma = (k * self.get_rms_dt(rms_dt) * (w - wo)**2 * (w - wo + a) / (w - wo + b))**0.5
        return irms_ma * 1e-3

    # noinspection PyUnusedLocal
    def _get_via_idc(self, bot_lp: Tuple[str, str], top_lp: Tuple[str, str], cut_w: int,
                     cut_h: int, bot_dim: Tuple[int, int], top_dim: Tuple[int, int],
                     array: bool, dc_temp: int) -> float:
        if bot_dim[0] > 0:
            bf = self._get_metal_idc_factor(bot_lp[0], bot_lp[1], bot_dim[0], bot_dim[1])
        else:
            bf = 1.0

        if top_dim[0] > 0:
            tf = self._get_metal_idc_factor(top_lp[0], top_lp[1], top_dim[0], top_dim[1])
        else:
            tf = 1.0

        factor = min(bf, tf)
        via_id = self.config['via_id'][(bot_lp, top_lp)]

        if via_id in ('M1_LiPo', 'M1_LiAct', 'M2_M1', 'M3_M2', 'M4_M3'):
            if cut_w == cut_h == 64:
                idc = 0.1
            elif cut_w != cut_h:
                idc = 0.2
            else:
                # we do not support 2X square via, as it has large
                # spacing rule to square/rectangle vias.
                raise ValueError('Unsupported via w/h: ({},{})'.format(cut_w, cut_h))
        else:
            idc = 0.4

        temp = self.get_dc_temp(dc_temp)
        return factor * self.get_idc_scale_factor(bot_lp[0], bot_lp[1], temp) * idc * 1e-3
