from collections import OrderedDict as _OrderedDict
from collections import deque
from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping
from typing import Any, TypeVar, overload

from typing_extensions import Self, override

__all__ = (
    "AttributeDict",
    "AttributeDictMixin",
    "BufferMap",
    "ChainMap",
    "ConfigurationView",
    "DictAttribute",
    "Evictable",
    "LimitedSet",
    "Messagebuffer",
    "OrderedDict",
    "force_mapping",
    "lpmerge",
)

_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
_T = TypeVar("_T")

class OrderedDict(_OrderedDict[_KT, _VT]):
    def _LRUkey(self) -> Any: ...

def force_mapping(m: Mapping[_KT, _VT] | None) -> Mapping[_KT, _VT]: ...
def lpmerge(L: list[Any], R: list[Any]) -> list[Any]: ...

class AttributeDictMixin:
    def __getattr__(self, k: str) -> Any: ...
    @override
    def __setattr__(self, key: str, value: Any) -> None: ...

class AttributeDict(dict[str, Any], AttributeDictMixin):
    def __init__(self, *args: Any, **kwargs: Any) -> None: ...

class BufferMap(dict[_KT, _VT]):
    Buffer: type[Messagebuffer]
    Empty: type[BaseException]
    maxsize: int | None
    bufmaxsize: int | None
    total: int
    def __init__(
        self,
        maxsize: int,
        iterable: Iterable[tuple[_KT, _VT]] | None = None,
        bufmaxsize: int = 1000,
    ) -> None: ...
    def evict(self) -> None: ...
    def extend(self, key: _KT, it: Iterable[_VT]) -> None: ...
    def put(self, key: _KT, item: _VT) -> None: ...
    def take(self, key: _KT, *default: _VT) -> _VT: ...

class ChainMap(MutableMapping[str, Any]):
    maps: list[Mapping[str, Any]] | None
    changes: dict[str, Any] | None
    defaults: list[Mapping[str, Any]] | None
    key_t: type[str] | None
    def __init__(self, *maps: Mapping[str, Any], **kwargs: Any) -> None: ...
    def __bool__(self) -> bool: ...
    def __copy__(self) -> Self: ...
    @override
    def __getitem__(self, key: str) -> Any: ...
    def __missing__(self, key: str) -> Any: ...
    @override
    def __setitem__(self, key: str, value: Any) -> None: ...
    @override
    def __delitem__(self, key: str) -> None: ...
    @override
    def __iter__(self) -> Iterator[str]: ...
    @override
    def __len__(self) -> int: ...
    def add_defaults(self, d: Mapping[str, Any]) -> None: ...
    def bind_to(self, callback: Callable[[MutableMapping[str, Any]], None]) -> None: ...
    def copy(self) -> Self: ...
    @classmethod
    def fromkeys(cls, iterable: Iterable[str], *args: Any) -> Self: ...
    @overload
    def get(self, key: str) -> Any: ...
    @overload
    def get(self, key: str, default: _T) -> Any | _T: ...  # pyright: ignore[reportIncompatibleMethodOverride]
    def iteritems(self) -> Iterator[tuple[str, Any]]: ...
    def iterkeys(self) -> Iterator[str]: ...
    def itervalues(self) -> Iterator[Any]: ...
    @overload
    def pop(self, key: str) -> Any: ...
    @overload
    def pop(self, key: str, default: _T) -> Any | _T: ...  # pyright: ignore[reportIncompatibleMethodOverride]
    @override
    def setdefault(self, key: str, default: Any = None) -> Any: ...

class ConfigurationView(ChainMap, AttributeDictMixin):
    def __init__(
        self,
        changes: dict[str, Any],
        defaults: Mapping[str, Any] | None = None,
        keys: Iterable[str] | None = None,
        prefix: str | None = None,
    ) -> None: ...
    def first(self, *keys: str) -> Any: ...
    @overload
    def get(self, key: str) -> Any: ...
    @overload
    def get(self, key: str, default: _T) -> Any | _T: ...
    def swap_with(self, other: ConfigurationView) -> None: ...

class DictAttribute(dict[str, Any]):
    obj: Any
    def __init__(self, obj: Any) -> None: ...
    @override
    def get(self, key: str, default: Any = None) -> Any: ...
    @override
    def setdefault(self, key: str, default: Any = None) -> Any: ...
    def iteritems(self) -> Iterator[tuple[str, Any]]: ...
    def iterkeys(self) -> Iterator[str]: ...
    def itervalues(self) -> Iterator[Any]: ...

class Evictable:
    Empty: type[BaseException]
    def evict(self) -> None: ...

class LimitedSet(Evictable):
    max_heap_percent_overload: int
    maxlen: int
    expires: float
    minlen: int
    def __init__(
        self,
        maxlen: int = 0,
        expires: float = 0,
        data: Iterable[Any] | None = None,
        minlen: int = 0,
    ) -> None: ...
    def add(self, item: Any, now: float | None = None) -> None: ...
    def as_dict(self) -> dict[Any, float]: ...
    def clear(self) -> None: ...
    def discard(self, item: Any) -> None: ...
    def pop(self, default: Any = None) -> Any: ...
    def pop_value(self, item: Any) -> None: ...
    def purge(self, now: float | None = None) -> None: ...
    def update(self, other: Iterable[Any]) -> None: ...
    def __contains__(self, value: object) -> bool: ...
    def __iter__(self) -> Iterator[Any]: ...
    def __len__(self) -> int: ...
    def __bool__(self) -> bool: ...

class Messagebuffer:
    Empty: type[BaseException]
    maxsize: int
    def __init__(
        self,
        maxsize: int,
        iterable: Iterable[Any] | None = None,
        deque: type[deque[Any]] = ...,
    ) -> None: ...
    def extend(self, it: Iterable[Any]) -> None: ...
    def put(self, item: Any) -> None: ...
    def take(self, *default: Any) -> Any: ...
    def __contains__(self, item: Any) -> bool: ...
    def __getitem__(self, index: int) -> Any: ...
    def __iter__(self) -> Iterator[Any]: ...
    def __len__(self) -> int: ...
    def __reversed__(self) -> Iterator[Any]: ...
