from __future__ import annotations

import enum

import typing
from typing import overload

from cohdl.utility import Span
from cohdl._core._unsigned import Unsigned
from cohdl._core._signed import Signed

from cohdl._core._bit import Bit, BitState
from cohdl._core._integer import Integer
from cohdl._core._boolean import _NullFullType
from cohdl._core._primitive_type import _PrimitiveType

class InvalidOverload: ...

class BitOrder(enum.Enum):
    DOWNTO = enum.auto()
    UPTO = enum.auto()

class BitVector(_PrimitiveType):
    def __class_getitem__(cls, offset) -> type[BitVector]: ...
    @property
    def width(self) -> int: ...
    @property
    def order(self) -> BitVector: ...
    def __init__(
        self,
        val: None | BitVector | str | _NullFullType | Span[Bit] = None,
    ) -> None: ...
    def __iter__(self) -> list[Bit]: ...
    def copy(self) -> BitVector: ...
    @overload
    def right(self, width=None, rest=None) -> Bit: ...
    @overload
    def right(self, width: int | None, rest: int | None) -> BitVector: ...
    @overload
    def left(self, width=None, rest=None) -> Bit: ...
    @overload
    def left(self, width: int | None, rest: int | None) -> BitVector: ...
    @overload
    def lsb(self, width=None, rest=None) -> Bit: ...
    @overload
    def lsb(self, width: int | None, rest: int | None) -> BitVector: ...
    @overload
    def msb(self, width=None, rest=None) -> Bit: ...
    @overload
    def msb(self, width: int | None, rest: int | None) -> BitVector: ...
    def __bool__(self) -> bool: ...
    def __invert__(self) -> BitVector: ...
    def __inv__(self) -> BitVector: ...
    @overload
    def __and__(self, other: Signed | Unsigned) -> InvalidOverload: ...
    @overload
    def __and__(self, other: BitVector) -> BitVector: ...
    @overload
    def __or__(self, other: Signed | Unsigned) -> InvalidOverload: ...
    @overload
    def __or__(self, other: BitVector) -> BitVector: ...
    @overload
    def __xor__(self, other: Signed | Unsigned) -> InvalidOverload: ...
    @overload
    def __xor__(self, other: BitVector) -> BitVector: ...
    def __eq__(self, other: BitVector) -> bool: ...
    def __ne__(self, other: BitVector) -> bool: ...
    def __matmul__(self, rhs: Bit | BitVector) -> BitVector: ...
    def __rmatmul__(self, lhs: Bit) -> BitVector: ...
    def __len__(self) -> int: ...
    @overload
    def __getitem__(self, key: int | Integer) -> Bit: ...
    @overload
    def __getitem__(self, key: slice) -> BitVector: ...
    @overload
    def __getitem__(self, key: list | tuple) -> BitVector: ...
    @overload
    def __setitem__(self, key: int | Integer, value: Bit): ...
    @overload
    def __setitem__(self, key: slice, value: BitVector): ...
    def __str__(self) -> str: ...
    def __repr__(self) -> str: ...
    @property
    def unsigned(self: BitVector) -> Unsigned: ...
    @unsigned.setter
    def unsigned(self: BitVector, value): ...
    @property
    def signed(self) -> Signed: ...
    @signed.setter
    def signed(self, value: BitVector): ...
    @property
    def bitvector(self) -> BitVector: ...
    @bitvector.setter
    def bitvector(self, value: BitVector): ...
