#!/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 typing import List, Optional

from .base import parse_filename as base_parse_filename


CornerTypeMappings = {}
# "fs" is sometimes called "wp" meaning worst-case power,
CornerTypeMappings["wp"] = "fs"
# "sf" is sometimes called "ws" meaning worst-case speed
CornerTypeMappings["ws"] = "sf"


class CornerType(Flag):
    """
    >>> CornerType.parse('t')
    CornerType.t
    >>> CornerType.parse('tt')
    [CornerType.t, CornerType.t]
    >>> CornerType.parse('wp')
    [CornerType.f, CornerType.s]
    """
    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:
            o = []
            for c in s:
                o.append(cls.parse(c))
            return o
        return getattr(cls, s)

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

    def __str__(self):
        return self.value



class CornerFlag(Flag):
    nointpr = 'No internal power'
    lv = 'Low voltage'
    ccsnoise = 'Composite Current Source Noise'

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

    def __str__(self):
        return self.value

@dataclass
class Corner:
    volts: List[float]
    temps: List[int]
    flags: List[CornerFlag]
    types: Optional[List[CornerType]] = None


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('sky130_fd_io-top_ground_padonlyv2-tt_1p80V_3p30V_3p30V_25C.wrap.lib')
    Corner(volts=[1.8, 3.3, 3.3], temps=[25], flags=[], types=[CornerType.t, CornerType.t])

    """
    cell, extra, extension = base_parse_filename(pathname)

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

    if not extra:
        raise ValueError('No corners found in: {!r}'.format(pathname))

    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', '-')))
        elif hasattr(CornerFlag, b):
            kw['flags'].append(getattr(CornerFlag, b))
        else:
            assert 'types' not in kw, (kw, b)
            kw['types'] = CornerType.parse(b)

    return Corner(**kw)



# 1p60V 5p50V n40C




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