# Copyright (c) 2021 - 2025, Ilan Schnell; All Rights Reserved
#
# This stub, as well as util.pyi, are tested with Python 3.10 and mypy 1.11.2

from collections.abc import Iterable, Iterator, Sequence
from unittest.runner import TextTestResult

from typing import Any, BinaryIO, Dict, Union, overload, NamedTuple


CodeDict = Dict[Any, bitarray]
# Python 3.12 has abc.Buffer which should be used instead
BytesLike = Union[bytes, bytearray]


class BufferInfo(NamedTuple):
    address: int
    nbytes: int
    endian: str
    padbits: int
    alloc: int
    readonly: bool
    imported: bool
    exports: int


class decodetree:
    def __init__(self, code: CodeDict) -> None: ...
    def complete(self) -> bool: ...
    def nodes(self) -> int: ...
    def todict(self) -> CodeDict: ...


class bitarray:
    def __init__(self,
                 initializer: Union[int, str, Iterable[int], None] = ...,
                 endian: Union[str, None] = ...,
                 buffer: Any = ...) -> None: ...

    def all(self) -> bool: ...
    def any(self) -> bool: ...
    def append(self, value: int) -> None: ...
    def buffer_info(self) -> BufferInfo: ...
    def bytereverse(self,
                    start: int = ...,
                    stop: int = ...) -> None: ...

    def clear(self) -> None: ...
    def copy(self) -> bitarray: ...
    def count(self,
              sub_bitarray: Union[bitarray, int] = ...,
              start: int = ...,
              stop: int = ...,
              step: int = ...) -> int: ...

    def encode(self, code: CodeDict, x: Iterable) -> None: ...
    def decode(self,
               code: Union[CodeDict, decodetree]) -> Iterator: ...

    def extend(self, x: Union[str, Iterable[int]]) -> None: ...
    def fill(self) -> int: ...
    def find(self,
             sub_bitarray: Union[bitarray, int],
             start: int = ...,
             stop: int = ...,
             right: int = ...) -> int: ...

    def frombytes(self, a: BytesLike) -> None: ...
    def fromfile(self, f: BinaryIO, n: int = ...) -> None: ...
    def index(self,
              sub_bitarray: Union[bitarray, int],
              start: int = ...,
              stop: int = ...,
              right: int = ...) -> int: ...

    def insert(self, i: int, value: int) -> None: ...
    def invert(self, i: int = ...) -> None: ...

    def search(self,
               sub_bitarray: Union[bitarray, int],
               start: int = ...,
               stop: int = ...,
               right: int = ...) -> Iterator[int]: ...

    def pack(self, b: BytesLike) -> None: ...
    def pop(self, i: int = ...) -> int: ...
    def remove(self, value: int) -> None: ...
    def reverse(self) -> None: ...

    def setall(self, value: int) -> None: ...
    def sort(self, reverse: int) -> None: ...
    def to01(self,
             group: int = ...,
             sep: str = ...) -> str: ...
    def tobytes(self) -> bytes: ...
    def tofile(self, f: BinaryIO) -> None: ...
    def tolist(self) -> list[int]: ...
    def unpack(self,
               zero: bytes = ...,
               one: bytes = ...) -> bytes: ...

    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...
    @overload
    def __getitem__(self, i: int) -> int: ...
    @overload
    def __getitem__(self,
                    s: Union[slice, bitarray, Sequence]) -> bitarray: ...
    @overload
    def __setitem__(self,
                    i: Union[int, slice, Sequence],
                    o: int) -> None: ...
    @overload
    def __setitem__(self,
                    s: Union[slice, bitarray, Sequence],
                    o: bitarray) -> None: ...
    def __delitem__(self,
                    i: Union[int, slice, bitarray, Sequence]) -> None: ...

    def __buffer__(self, flags: int, /) -> memoryview: ...
    def __release_buffer__(self, buffer: memoryview, /) -> None: ...

    def __add__(self, other: bitarray) -> bitarray: ...
    def __iadd__(self, other: bitarray) -> bitarray: ...
    def __mul__(self, n: int) -> bitarray: ...
    def __imul__(self, n: int) -> bitarray: ...
    def __rmul__(self, n: int) -> bitarray: ...

    def __ge__(self, other: bitarray) -> bool: ...
    def __gt__(self, other: bitarray) -> bool: ...
    def __le__(self, other: bitarray) -> bool: ...
    def __lt__(self, other: bitarray) -> bool: ...

    def __and__(self, other: bitarray) -> bitarray: ...
    def __or__(self, other: bitarray) -> bitarray: ...
    def __xor__(self, other: bitarray) -> bitarray: ...
    def __iand__(self, other: bitarray) -> bitarray: ...
    def __ior__(self, other: bitarray) -> bitarray: ...
    def __ixor__(self, other: bitarray) -> bitarray: ...
    def __invert__(self) -> bitarray: ...
    def __lshift__(self, n: int) -> bitarray: ...
    def __rshift__(self, n: int) -> bitarray: ...
    def __ilshift__(self, n: int) -> bitarray: ...
    def __irshift__(self, n: int) -> bitarray: ...

    # data descriptors
    @property
    def endian(self) -> str: ...
    @property
    def nbytes(self) -> int: ...
    @property
    def padbits(self) -> int: ...
    @property
    def readonly(self) -> bool: ...


class frozenbitarray(bitarray):
    def __hash__(self) -> int: ...


__version__: str
def bits2bytes(n: int) -> int: ...
def get_default_endian() -> str: ...
def test(verbosity: int = ...) -> TextTestResult: ...
def _set_default_endian(endian: str) -> None: ...
def _sysinfo(key: str) -> int: ...
def _bitarray_reconstructor(cls: type,
                            buffer: bytes,
                            endian: str,
                            padbits: int,
                            readonly: int) -> bitarray: ...
