from collections.abc import Callable, Iterable, Iterator, MutableSequence, Sequence
from typing import Any, Final, Generic, TypeVar, overload
from typing_extensions import Self, TypeAlias

from _typeshed import SupportsRichComparison

__all__ = [
    "KeyFunc",
    "_OrderT",
    "SortedKeyList",
    "SortedList",
    "SupportsRichComparison",
]

_T = TypeVar("_T")
_OrderT = TypeVar("_OrderT", bound=SupportsRichComparison)
KeyFunc: TypeAlias = Callable[[_T], _OrderT]

class SortedList(MutableSequence[_T]):
    DEFAULT_LOAD_FACTOR: Final[int] = ...
    @overload
    def __new__(cls, key: KeyFunc[_T, _OrderT]) -> SortedKeyList[_T, _OrderT]: ...
    @overload
    def __new__(cls, iterable: None = ..., key: None = ...) -> SortedList[_OrderT]: ...
    @overload
    def __new__(
        cls, iterable: Iterable[_OrderT], key: None = ...
    ) -> SortedList[_OrderT]: ...
    @overload
    def __new__(
        cls,
        iterable: Iterable[_T] | None,
        key: KeyFunc[_T, _OrderT],
    ) -> SortedKeyList[_T, _OrderT]: ...
    @property
    def key(self) -> KeyFunc[_T, Any] | None: ...
    def clear(self) -> None: ...
    def add(self, value: _T) -> None: ...
    def update(self, iterable: Iterable[_T]) -> None: ...
    def discard(self, value: _T) -> None: ...
    def remove(self, value: _T) -> None: ...
    # The implementation requires that value is T, but the base class accepts
    # Any, which we can't narrow. As a compromise, we narrow anyway and ignore
    # the error. The result is that __contains__ is type safe when using
    # SortedList directly, but not safe if SortedList is assigned to a more
    # general collection type.
    def __contains__(self, value: _T) -> bool: ...  # type: ignore[override]
    def __delitem__(self, index: int | slice) -> None: ...
    @overload
    def __getitem__(self, index: int) -> _T: ...
    @overload
    def __getitem__(self, index: slice) -> list[_T]: ...
    @overload
    def __setitem__(self, index: int, value: _T) -> None: ...
    @overload
    def __setitem__(self, index: slice, value: Iterable[_T]) -> None: ...
    # def __iter__(self) -> Iterator[T]: ...
    def __reversed__(self) -> Iterator[_T]: ...
    def __len__(self) -> int: ...
    # def reverse(self) -> None: ...
    def islice(
        self,
        start: int | None = ...,
        stop: int | None = ...,
        reverse: bool = ...,
    ) -> Iterator[_T]: ...
    def irange(
        self,
        minimum: _T | None = ...,
        maximum: _T | None = ...,
        inclusive: tuple[bool, bool] = ...,
        reverse: bool = ...,
    ) -> Iterator[_T]: ...
    def bisect_left(self, value: _T) -> int: ...
    def bisect_right(self, value: _T) -> int: ...
    def bisect(self, value: _T) -> int: ...
    def count(self, value: _T) -> int: ...
    def copy(self) -> Self: ...
    def __copy__(self) -> Self: ...
    # def append(self, value: T) -> None: ...
    # def extend(self, values: Iterable[T]) -> None: ...
    def insert(self, index: int, value: _T) -> None: ...
    # def pop(self, index: int = ...) -> T: ...
    def index(
        self, value: _T, start: int | None = ..., stop: int | None = ...
    ) -> int: ...
    def __add__(self, other: Iterable[_T]) -> Self: ...
    def __radd__(self, other: Iterable[_T]) -> Self: ...
    def __iadd__(self, other: Iterable[_T]) -> Self: ...
    def __mul__(self, num: int) -> Self: ...
    def __rmul__(self, num: int) -> Self: ...
    def __imul__(self, num: int) -> Self: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __lt__(self, other: Sequence[_T]) -> bool: ...
    def __gt__(self, other: Sequence[_T]) -> bool: ...
    def __le__(self, other: Sequence[_T]) -> bool: ...
    def __ge__(self, other: Sequence[_T]) -> bool: ...
    # Despite being named as a private method, this is documented in the API.
    def _reset(self, load: int) -> None: ...

class SortedKeyList(SortedList[_T], Generic[_T, _OrderT]):
    # The constructor always returns SortedKeyList instances, and uses the
    # identity function as the default key func.
    @overload
    def __new__(
        cls, iterable: Iterable[_OrderT]
    ) -> SortedKeyList[_OrderT, _OrderT]: ...
    @overload
    def __new__(cls, key: KeyFunc[_T, _OrderT]) -> SortedKeyList[_T, _OrderT]: ...
    @overload
    def __new__(cls, iterable: None = ..., key: None = ...) -> Self: ...
    @overload
    def __new__(
        cls, iterable: Iterable[_OrderT], key: None
    ) -> SortedKeyList[_OrderT, _OrderT]: ...
    @overload
    def __new__(
        cls,
        iterable: Iterable[_T] | None,
        key: KeyFunc[_T, _OrderT],
    ) -> SortedKeyList[_T, _OrderT]: ...
    @property
    def key(self) -> KeyFunc[_T, _OrderT]: ...
    def irange_key(
        self,
        min_key: _OrderT | None = ...,
        max_key: _OrderT | None = ...,
        inclusive: tuple[bool, bool] = ...,
        reverse: bool = ...,
    ) -> Iterator[_T]: ...
    def bisect_key_left(self, key: _OrderT) -> int: ...
    def bisect_key_right(self, key: _OrderT) -> int: ...
    def bisect_key(self, key: _OrderT) -> int: ...

SortedListWithKey = SortedKeyList
