from collections.abc import Callable, Iterable, Iterator, MutableMapping, MutableSequence, Sequence
from typing import Any, Protocol, SupportsIndex, TypeVar, overload, type_check_only

from google.protobuf.descriptor import Descriptor, FieldDescriptor
from google.protobuf.internal.message_listener import MessageListener
from google.protobuf.internal.python_message import GeneratedProtocolMessageType
from google.protobuf.message import Message

_T = TypeVar("_T")
_K = TypeVar("_K", bound=bool | int | str)
_ScalarV = TypeVar("_ScalarV", bound=bool | int | float | str | bytes)
_MessageV = TypeVar("_MessageV", bound=Message)

@type_check_only
class _ValueChecker(Protocol[_T]):
    def CheckValue(self, proposed_value: _T) -> _T: ...
    def DefaultValue(self) -> _T: ...

class BaseContainer(Sequence[_T]):
    __slots__ = ["_message_listener", "_values"]
    def __init__(self, message_listener: MessageListener) -> None: ...

    @overload
    def __getitem__(self, key: SupportsIndex) -> _T: ...
    @overload
    def __getitem__(self, key: slice) -> list[_T]: ...

    def __len__(self) -> int: ...
    def __ne__(self, other: object) -> bool: ...
    def __hash__(self) -> int: ...
    # Same as list.sort, the extra sort_function kwarg errors in Python 3
    def sort(self, *, key: Callable[[_T], Any] | None = None, reverse: bool = False) -> None: ...
    def reverse(self) -> None: ...

class RepeatedScalarFieldContainer(BaseContainer[_ScalarV], MutableSequence[_ScalarV]):
    __slots__ = ["_type_checker"]
    def __init__(
        self, message_listener: MessageListener, type_checker: _ValueChecker[_ScalarV], field: FieldDescriptor | None = None
    ) -> None: ...
    def append(self, value: _ScalarV) -> None: ...
    def insert(self, key: int, value: _ScalarV) -> None: ...
    def extend(self, elem_seq: Iterable[_ScalarV] | None) -> None: ...
    def MergeFrom(self, other: RepeatedScalarFieldContainer[_ScalarV] | Iterable[_ScalarV]) -> None: ...
    def remove(self, elem: _ScalarV) -> None: ...
    def pop(self, key: int = -1) -> _ScalarV: ...

    @overload
    def __setitem__(self, key: int, value: _ScalarV) -> None: ...
    @overload
    def __setitem__(self, key: slice, value: Iterable[_ScalarV]) -> None: ...

    def __delitem__(self, key: int | slice) -> None: ...
    def __eq__(self, other: object) -> bool: ...
    def __deepcopy__(self, unused_memo: Any = None) -> RepeatedScalarFieldContainer[_ScalarV]: ...
    def __array__(self, dtype: Any = None, copy: bool | None = None) -> Any: ...  # Any: numpy types

class RepeatedCompositeFieldContainer(BaseContainer[_MessageV], MutableSequence[_MessageV]):
    __slots__ = ["_message_descriptor"]
    def __init__(self, message_listener: MessageListener, message_descriptor: Descriptor) -> None: ...
    def add(self, **kwargs: Any) -> _MessageV: ...  # Any: field names and values
    def append(self, value: _MessageV) -> None: ...
    def insert(self, key: int, value: _MessageV) -> None: ...
    def extend(self, elem_seq: Iterable[_MessageV]) -> None: ...
    def MergeFrom(self, other: RepeatedCompositeFieldContainer[_MessageV] | Iterable[_MessageV]) -> None: ...
    def remove(self, elem: _MessageV) -> None: ...
    def pop(self, key: int = -1) -> _MessageV: ...

    @overload
    def __setitem__(self, key: int, value: _MessageV) -> None: ...
    @overload
    def __setitem__(self, key: slice, value: Iterable[_MessageV]) -> None: ...

    def __delitem__(self, key: int | slice) -> None: ...
    def __eq__(self, other: object) -> bool: ...

class ScalarMap(MutableMapping[_K, _ScalarV]):
    __slots__ = ["_key_checker", "_value_checker", "_values", "_message_listener", "_entry_descriptor"]
    def __init__(
        self,
        message_listener: MessageListener,
        key_checker: _ValueChecker[_K],
        value_checker: _ValueChecker[_ScalarV],
        entry_descriptor: Descriptor,
    ) -> None: ...
    def __getitem__(self, key: _K) -> _ScalarV: ...

    @overload
    def get(self, key: _K, default: None = None) -> _ScalarV | None: ...
    @overload
    def get(self, key: _K, default: _ScalarV) -> _ScalarV: ...
    @overload
    def get(self, key: _K, default: _T) -> _ScalarV | _T: ...

    def __setitem__(self, key: _K, value: _ScalarV) -> None: ...
    def __delitem__(self, key: _K) -> None: ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[_K]: ...
    def __eq__(self, other: object) -> bool: ...
    def setdefault(self, key: _K, value: _ScalarV | None = None) -> _ScalarV: ...
    def MergeFrom(self, other: ScalarMap[_K, _ScalarV]) -> None: ...
    def InvalidateIterators(self) -> None: ...
    def clear(self) -> None: ...
    def GetEntryClass(self) -> GeneratedProtocolMessageType: ...

class MessageMap(MutableMapping[_K, _MessageV]):
    __slots__ = ["_key_checker", "_values", "_message_listener", "_message_descriptor", "_entry_descriptor"]
    def __init__(
        self,
        message_listener: MessageListener,
        message_descriptor: Descriptor,
        key_checker: _ValueChecker[_K],
        entry_descriptor: Descriptor,
    ) -> None: ...
    def __getitem__(self, key: _K) -> _MessageV: ...
    def get_or_create(self, key: _K) -> _MessageV: ...

    @overload
    def get(self, key: _K, default: None = None) -> _MessageV | None: ...
    @overload
    def get(self, key: _K, default: _MessageV) -> _MessageV: ...
    @overload
    def get(self, key: _K, default: _T) -> _MessageV | _T: ...

    def __setitem__(self, key: _K, value: _MessageV) -> None: ...
    def __delitem__(self, key: _K) -> None: ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[_K]: ...
    def __eq__(self, other: object) -> bool: ...
    def setdefault(self, key: _K, value: _MessageV | None = None) -> _MessageV: ...
    def MergeFrom(self, other: MessageMap[_K, _MessageV]) -> None: ...
    def InvalidateIterators(self) -> None: ...
    def clear(self) -> None: ...
    def GetEntryClass(self) -> GeneratedProtocolMessageType: ...

class UnknownFieldRef:
    def __init__(self, parent: UnknownFieldSet, index: int) -> None: ...
    @property
    def field_number(self) -> int: ...
    @property
    def wire_type(self) -> int: ...
    @property
    def data(self) -> Any: ...  # Any: int, bytes, or UnknownFieldSet

class UnknownFieldSet:
    __slots__ = ["_values"]
    def __init__(self) -> None: ...
    def __getitem__(self, index: int) -> UnknownFieldRef: ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[UnknownFieldRef]: ...
