from hwt.doc_markers import internal
from hwt.hdl.types.hdlType import HdlType
from hwt.serializer.generic.indent import getIndent
from pyMathBitPrecise.bits3t import Bits3t


BITS_DEFAUTL_SIGNED = None
BITS_DEFAUTL_FORCEVECTOR = False
BITS_DEFAUTL_NEGATED = False


class Bits(HdlType, Bits3t):
    """
    Elemental HDL type representing bits (vector or single bit)
    """

    def __init__(self, bit_length, signed=BITS_DEFAUTL_SIGNED,
                 force_vector=BITS_DEFAUTL_FORCEVECTOR,
                 negated=BITS_DEFAUTL_NEGATED,
                 name=None,
                 const=False,
                 strict_sign=True, strict_width=True):
        """
        :param negated: if true the value is in negated form
        """
        self.negated = negated
        HdlType.__init__(self, const=const)
        bit_length = int(bit_length)
        assert bit_length > 0, bit_length
        Bits3t.__init__(self, bit_length, signed, name=name,
                        force_vector=force_vector,
                        strict_sign=strict_sign, strict_width=strict_width)

    @internal
    def domain_size(self):
        """
        :return: how many values can have specified type
        """
        return int(2 ** self.bit_length())

    @internal
    @classmethod
    def get_auto_cast_fn(cls):
        from hwt.hdl.types.bitsCast import convertBits
        return convertBits

    @internal
    @classmethod
    def get_reinterpret_cast_fn(cls):
        from hwt.hdl.types.bitsCast import reinterpretBits
        return reinterpretBits

    @internal
    @classmethod
    def getValueCls(cls):
        try:
            return cls._valCls
        except AttributeError:
            from hwt.hdl.types.bitsVal import BitsVal
            cls._valCls = BitsVal
            return cls._valCls

    def __hash__(self):
        return hash((Bits3t.__hash__(self), self.const))

    def __eq__(self, other):
        return  Bits3t.__eq__(self, other) and self.const == other.const

    def __repr__(self, indent=0, withAddr=None, expandStructs=False):
        """
        :param indent: number of indentation
        :param withAddr: if is not None is used as a additional
            information about on which address this type is stored
            (used only by HStruct)
        :param expandStructs: expand HStructTypes (used by HStruct and HArray)
        """
        constr = []
        if self.name is not None:
            constr.append('"%s"' % self.name)
        c = self.bit_length()
        if c == 1:
            constr.append("1bit")
        else:
            constr.append(f"{c:d}bits")
        if self.force_vector:
            constr.append("force_vector")
        if self.signed:
            constr.append("signed")
        if self.const:
            constr.append("const")
        elif self.signed is False:
            constr.append("unsigned")
        if not self.strict_sign:
            constr.append("strict_sign=False")
        if not self.strict_width:
            constr.append("strict_width=False")

        return "%s<%s, %s>" % (getIndent(indent),
                               self.__class__.__name__,
                               ", ".join(constr))

@@ -168,17 +168,16 @@
 Bits3t%0A%0A
-%0A
 BITS_DEF
@@ -997,16 +997,38 @@
 e_vector
+ or signed is not None
 ,%0A      
@@ -2569,24 +2569,104 @@
 end(%221bit%22)%0A
+            if self.force_vector:%0A                constr.append(%22force_vector%22)%0A
         else
@@ -2707,16 +2707,17 @@
 %7Dbits%22)%0A
+%0A
         
@@ -2720,36 +2720,29 @@
     if self.
-force_vector
+const
 :%0A          
@@ -2754,39 +2754,33 @@
 str.append(%22
-force_vector
+const
 %22)%0A
+%0A
         if s
@@ -2831,66 +2831,8 @@
 d%22)%0A
-        if self.const:%0A            constr.append(%22const%22)%0A
     
@@ -2892,32 +2892,33 @@
 end(%22unsigned%22)%0A
+%0A
         if not s
@@ -2981,16 +2981,17 @@
 False%22)%0A
+%0A
         

fix lit '' vs "" for 1b unsigned lit