from pymoku.applets import ratelimit

from pymoku.registers import _reg_prop, _reg_prop_list
from pyqtgraph.parametertree import Parameter, ParameterTree, registerParameterType
import pyqtgraph.parametertree.parameterTypes as pTypes


class RegParameter(Parameter):
    def __init__(self, **opts):
        self.attr = opts['reg_prop']
        self.inst = opts['reg_instance']

        length = self.attr.length
        if self.attr._type == 'unsigned':
            limits = (0, 2**length - 1)
        else:
            limits = (-2**(length - 1), 2**(length - 1) - 1)

        opts.update(readonly=self.attr.readonly,
                    value=self.attr.getter(self.inst),
                    int=True,
                    step=1,
                    limits=limits)

        super().__init__(**opts)

    @ratelimit
    def setValue(self, value):
        self.attr.setter(self.inst, value)

    def value(self):
        return self.attr.getter(self.inst)


class RegUnsignedParameter(RegParameter):
    @property
    def itemClass(self):
        return pTypes.NumericParameterItem


class RegBoolParameter(RegParameter):
    @property
    def itemClass(self):
        return pTypes.BoolParameterItem


registerParameterType('unsigned', RegUnsignedParameter)
registerParameterType('signed', RegUnsignedParameter)
registerParameterType('boolean', RegBoolParameter)
registerParameterType('choice', Parameter)
registerParameterType('slv', RegUnsignedParameter)
registerParameterType('input', Parameter)


def params_from_regs(regs):
    d = []
    for k in dir(regs):
        attr = object.__getattribute__(regs, k)

        if isinstance(attr, _reg_prop_list):
            children = [dict(name=f'[{i:d}]', type=reg._type, reg_prop=reg, reg_instance=regs)
                        for i, reg in enumerate(attr._reg_items)]
            d.append(dict(name=k, type='group', children=children))
        elif isinstance(attr, _reg_prop):
            d.append(dict(name=k, type=attr._type, reg_prop=attr, reg_instance=regs))

    for prefix, child in regs._children.items():
        d.append(dict(name=prefix, type='group', children=params_from_regs(child)))

    return d


class RegisterTree(ParameterTree):
    def __init__(self, moku, instr):
        super().__init__(showHeader=False)

        with instr.cached_registers(write=False):
            params = Parameter.create(name=instr.NAME, type='group', children=params_from_regs(instr))
            self.setParameters(params, showTop=True)
