#!/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 Optional, Tuple

from pybag.core import BBox

from xbase.layout.enum import MOSType
from xbase.layout.data import LayoutInfoBuilder


def add_base(builder: LayoutInfoBuilder, row_type: MOSType, threshold: str, imp_y: Tuple[int, int],
             rect: BBox, well_x: Optional[Tuple[int, int]] = None) -> None:
    # draws nwell, n+ implant (ndsm) and p+ implant (pdsm)
    # for non mos devices (corners, edges, etc)

    if rect.is_physical():
        if not row_type.is_pwell:
            well_lp = ('nwell', 'drawing')
            if well_x is None:
                builder.add_rect_arr(well_lp, rect)
            else:
                builder.add_rect_arr(well_lp, BBox(well_x[0], rect.yl, well_x[1], rect.yh))
            
        thres_lp = _get_thres_lp(row_type, threshold)
        if thres_lp[0] != '':
            builder.add_rect_arr(thres_lp, rect)


def add_base_mos(builder: LayoutInfoBuilder, row_type: MOSType, threshold: str, imp_y: Tuple[int, int],
                 rect: BBox, well_x: Optional[Tuple[int, int]] = None, imp_x: Optional[Tuple[int, int]] = None,
                 is_sub: bool = False) -> None:
    # new func draws nwell, n+ implant (ndsm) and p+ implant (pdsm)
    if rect.is_physical():
        # only draw nwells if not a tap cell and pch, or is tap cell and nch
        if (not row_type.is_pwell and not is_sub) or (is_sub and row_type.is_n_plus):
            well_lp = ('nwell', 'drawing')
            if well_x is None:
                builder.add_rect_arr(well_lp, rect)
            else:
                builder.add_rect_arr(well_lp, BBox(well_x[0], rect.yl, well_x[1], rect.yh))
            
        # draw the respective implant
        if row_type.is_n_plus:
            imp_lp = ('nsdm', 'drawing')
        else:
            imp_lp = ('psdm', 'drawing')
        if imp_x is None:
            imp_bbox = BBox(rect.xl, imp_y[0], rect.xh, imp_y[1])
        else:
            imp_bbox = BBox(imp_x[0], imp_y[0], imp_x[1], imp_y[1])
        builder.add_rect_arr(imp_lp,  imp_bbox)

        thres_lp = _get_thres_lp(row_type, threshold)
        if thres_lp[0] != '':
            builder.add_rect_arr(thres_lp, rect)


def get_arr_edge_dim(arr_dim: int, edge_min_dim: int, blk_pitch: int, edge_pitch: int = 1,
                     edge_offset: int = 0) -> int:
    dim_tot = -(-(arr_dim + 2 * edge_min_dim) // blk_pitch) * blk_pitch
    dim2 = dim_tot - arr_dim
    if dim2 & 1 == 1:
        if blk_pitch & 1 == 1:
            dim2 += blk_pitch
        else:
            raise RuntimeError(f'Parity Error: impossible to center ArrayBase with '
                               f'arr_dim={arr_dim}, blk_pitch={blk_pitch}, '
                               f'and edge_min_dim={edge_min_dim}.')

    ans = dim2 // 2
    if (ans - edge_offset) % edge_pitch != 0:
        # precondition: we know that edge_pitch divides blk_pitch
        blk_pitch2 = blk_pitch // 2
        if blk_pitch & 1 != 0 or (ans + blk_pitch2 - edge_offset) % edge_pitch != 0:
            raise RuntimeError(f'Parity Error: impossible to center ArrayBase with '
                               f'arr_dim={arr_dim}, blk_pitch={blk_pitch}, '
                               f'edge_min_dim={edge_min_dim}, edge_pitch={edge_pitch}, '
                               f'and edge_offset={edge_offset}')
        ans += blk_pitch2

    return ans


def _get_thres_lp(row_type: MOSType, threshold: str) -> Tuple[str, str]:
    if threshold == 'standard':
        return '', ''
    if threshold == 'lvt':
        return 'lvtn', 'drawing'
    if threshold == 'hvt':
        if row_type.is_n_plus:
            raise ValueError('Threshold hvt not supported for nmos')
        return 'hvtp', 'drawing'
    raise ValueError(f'unknown threshold: {threshold}')
