#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2020 The SkyWater PDK Authors.
#
# Use of this source code is governed by the Apache 2.0
# license that can be found in the LICENSE file or at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0

import re
import os

from enum import Flag
from dataclasses import dataclass
from dataclasses_json import dataclass_json
from typing import Tuple, Optional

from . import base
from .utils import OrderedFlag
from .utils import comparable_to_none
from .utils import dataclass_json_passthru_sequence_config as dj_pass_cfg


CornerTypeMappings = {}
# "wo" is "worst-case one" and corresponds to "fs"
CornerTypeMappings["wo"] = "fs"
# "wz" is "worst-case zero" and corresponds to "sf"
CornerTypeMappings["wz"] = "sf"
# "wp" is "worst-case power" and corresponds to "ff"
CornerTypeMappings["wp"] = "ff"
# "ws" is "worst-case speed" and corresponds to "ss"
CornerTypeMappings["ws"] = "ss"


class CornerType(OrderedFlag):
    """
    >>> CornerType.parse('t')
    CornerType.t
    >>> CornerType.parse('tt')
    [CornerType.t, CornerType.t]
    >>> CornerType.parse('wp')
    [CornerType.f, CornerType.f]
    """
    t = 'Typical'  # all  nominal (typical) values
    f = 'Fast'     # fast, that is, values that make transistors run faster
    s = 'Slow'     # slow

    @classmethod
    def parse(cls, s):
        if s in CornerTypeMappings:
            return cls.parse(CornerTypeMappings[s])
        if len(s) > 1:
            try:
                o = []
                for c in s:
                    o.append(cls.parse(c))
                return o
            except TypeError:
                raise TypeError("Unknown corner type: {}".format(s))
        if not hasattr(cls, s):
            raise TypeError("Unknown corner type: {}".format(s))
        return getattr(cls, s)

    def __repr__(self):
        return 'CornerType.'+self.name

    def __str__(self):
        return self.value

    def to_json(self):
        return self.name


class CornerFlag(OrderedFlag):
    nointpr = 'No internal power'
    lv = 'Low voltage'
    hv = 'High voltage'
    ccsnoise = 'Composite Current Source Noise'
    pwr = 'Power'
    xx = 'xx'
    w = 'w'

    @classmethod
    def parse(cls, s):
        if hasattr(cls, s):
            return getattr(cls, s)
        else:
            raise TypeError("Unknown CornerFlags: {}".format(s))

    def __repr__(self):
        return 'CornerFlag.'+self.name

    def __str__(self):
        return self.value

    def to_json(self):
        return self.name


@comparable_to_none
class OptionalTuple(tuple):
    pass


@comparable_to_none
@dataclass_json
@dataclass(frozen=True, order=True)
class Corner:
    corner: Tuple[CornerType, CornerType] = dj_pass_cfg()
    volts: Tuple[float, ...] = dj_pass_cfg()
    temps: Tuple[int, ...] = dj_pass_cfg()
    flags: Optional[Tuple[CornerFlag, ...]] = dj_pass_cfg(default=None)

    def __post_init__(self):
        if self.flags:
            object.__setattr__(self, 'flags', OptionalTuple(self.flags))


VOLTS_REGEX = re.compile('([0-9]p[0-9]+)V')
TEMP_REGEX = re.compile('(n?)([0-9][0-9]+)C')
def parse_filename(pathname):
    """Extract corner information from a filename.

    >>> parse_filename('tt_1p80V_3p30V_3p30V_25C')
    Corner(corner=(CornerType.t, CornerType.t), volts=(1.8, 3.3, 3.3), temps=(25,), flags=None)

    >>> parse_filename('sky130_fd_io__top_ground_padonlyv2__tt_1p80V_3p30V_3p30V_25C.wrap.lib')
    Corner(corner=(CornerType.t, CornerType.t), volts=(1.8, 3.3, 3.3), temps=(25,), flags=None)

    >>> parse_filename('sky130_fd_sc_ms__tt_1p80V_100C.wrap.json')
    Corner(corner=(CornerType.t, CornerType.t), volts=(1.8,), temps=(100,), flags=None)

    >>> parse_filename('sky130_fd_sc_ms__tt_1p80V_100C.wrap.lib')
    Corner(corner=(CornerType.t, CornerType.t), volts=(1.8,), temps=(100,), flags=None)

    >>> parse_filename('sky130_fd_sc_ms__tt_1p80V_25C_ccsnoise.wrap.json')
    Corner(corner=(CornerType.t, CornerType.t), volts=(1.8,), temps=(25,), flags=(CornerFlag.ccsnoise,))

    >>> parse_filename('sky130_fd_sc_ms__wp_1p65V_n40C.wrap.json')
    Corner(corner=(CornerType.f, CornerType.f), volts=(1.65,), temps=(-40,), flags=None)

    >>> parse_filename('sky130_fd_sc_ms__wp_1p95V_85C_pwr.wrap.lib')
    Corner(corner=(CornerType.f, CornerType.f), volts=(1.95,), temps=(85,), flags=(CornerFlag.pwr,))

    >>> parse_filename('sky130_fd_sc_ms__wp_1p95V_n40C_ccsnoise.wrap.json')
    Corner(corner=(CornerType.f, CornerType.f), volts=(1.95,), temps=(-40,), flags=(CornerFlag.ccsnoise,))

    >>> parse_filename('sky130_fd_sc_ms__wp_1p95V_n40C_pwr.wrap.lib')
    Corner(corner=(CornerType.f, CornerType.f), volts=(1.95,), temps=(-40,), flags=(CornerFlag.pwr,))

    >>> parse_filename('sky130_fd_sc_hd__a2111o_4__ss_1p76V_n40C.cell.json')
    Corner(corner=(CornerType.s, CornerType.s), volts=(1.76,), temps=(-40,), flags=None)

    """
    if base.SEPERATOR in pathname:
        cell, extra, extension = base.parse_filename(pathname)
    else:
        cell = None
        extra = pathname
        extension = ''

    if extension not in ('', 'lib', 'cell.lib', 'cell.json', 'wrap.lib', 'wrap.json'):
        raise ValueError('Not possible to extract corners from: {!r}'.format(extension))

    if not extra:
        extra = cell.name
        cell = None

    # FIXME: Hack?
    extra = extra.replace("lpflow_","")
    extra = extra.replace("udb_","")

    kw = {}
    kw['flags'] = []
    kw['volts'] = []
    kw['temps'] = []

    bits = extra.split("_")
    while len(bits) > 0:
        b = bits.pop(0)

        if VOLTS_REGEX.match(b):
            assert b.endswith('V'), b
            kw['volts'].append(float(b[:-1].replace('p', '.')))
        elif TEMP_REGEX.match(b):
            assert b.endswith('C'), b
            kw['temps'].append(int(b[:-1].replace('n', '-')))
        else:
            if 'corner' not in kw:
                kw['corner'] = CornerType.parse(b)
            else:
                kw['flags'].append(CornerFlag.parse(b))

    for k, v in kw.items():
        kw[k] = tuple(v)

    if not kw['flags']:
        del kw['flags']

    return Corner(**kw)



# 1p60V 5p50V n40C




if __name__ == "__main__":
    import doctest
    doctest.testmod()
