import re

from ee import EeException, EeVal
from ee.kicad import Component
from ee.kicad.make_bom import MakeBomStrategy
from ee.xml import types
from ee.part import fact_keys, Part

c_value_re = re.compile("([0-9]+\\.?[0-9]*[mupn]F)/([0-9]+\\.?[0-9]*[k]?V)/([0-9]+)%(?:/([A-Z][0-9][A-Z]))?")
r_value_re = re.compile(r"([^/]+)(?:/([^/]+)(?:/([^/]+))?)?")


class OlinuxinoMakeBomStrategy(MakeBomStrategy):

    @staticmethod
    def set_default(part: Part, fact_key: str, value):
        fact = part.find_fact(fact_key)
        if fact:
            return

        part.get_facts().append(types.Fact(key=fact_key, value=value))

    def process_part(self, component: Component, part: Part):
        debug = False

        print(component.ref)
        print("  value={}".format(component.value))
        print("  footprint={}".format(component.footprint))

        v = component.value

        fp_lib, fp_part = None, None
        if component.footprint:
            s = component.footprint.split(":")
            fp_lib, fp_part = s[0], s[1]

        fs = part.get_facts()

        na = v.startswith("NA(") and v.endswith(")") or v == "NA"
        if na:
            v = v[3:-1]

        if v == "":
            pass
        elif component.ref_type == "C":
            m = c_value_re.match(v)

            if not m:
                raise EeException("Bad value: {}".format(v))

            capacitance = m.group(1)
            voltage = m.group(2)
            tolerance = str(int(m.group(3))) + "%"
            rs_198_class_2 = m.group(4)

            if debug:
                print("    capacitance    {}".format(capacitance))
                print("    voltage        {}".format(voltage))
                print("    tolerance      {}".format(tolerance))
                if rs_198_class_2:
                    print("    rs_198_class_2 {}".format(rs_198_class_2))
                if na:
                    print("    NA".format())

            fs.append(types.Fact(key=fact_keys.capacitance, value=capacitance))
            fs.append(types.Fact(key=fact_keys.max_voltage, value=voltage))
            fs.append(types.Fact(key=fact_keys.value_tolerance, value=tolerance))
            if rs_198_class_2:
                fs.append(types.Fact(key=fact_keys.rs_198_class_2, value=rs_198_class_2))

        elif component.ref_type == "R":
            # NA
            # NA(510R)
            # NA(243R/1%)
            # 4.7k
            # 8.25k/1%
            # 120R
            # 0R(Board_Mounted)
            # 0.01R/1%/1206

            match = r_value_re.match(v)
            if not match:
                return part

            resistance, tolerance, size = match.groups()
            if resistance.endswith("R"):
                resistance = resistance[:-1]

            resistance = str(EeVal.parse(resistance))

            fs.append(types.Fact(key=fact_keys.resistance, value=resistance))
            if tolerance:
                fs.append(types.Fact(key=fact_keys.value_tolerance, value=tolerance))
            if size:
                fs.append(types.Fact(key=fact_keys.imperial_footprint_size, value=size))

            self.set_default(part, fact_keys.value_tolerance, "10%")
        else:
            fs.append(types.Fact(key=fact_keys.value, value=v))

        if na:
            fs.append(types.Fact(key=fact_keys.place_part, value="no"))

        # raise EeException("Unknown component kind: ref={}, ref type:{}, value={}, fp_lib={}, fp_part={}".
        #                   format(component.ref, component.ref_type, v, fp_lib, fp_part))
        return part


def make_bom_strategy():
    return OlinuxinoMakeBomStrategy()