from collections.abc import Callable
from collections.abc import Iterable
from collections.abc import Iterator
from collections.abc import Mapping
from typing import Literal
from typing import NoReturn
from typing import overload
from typing import TypeVar

from _typeshed import SupportsKeysAndGetItem
from _typeshed.wsgi import WSGIEnvironment

from .mixins import ImmutableHeadersMixin

D = TypeVar("D")
T = TypeVar("T")

class Headers(dict[str, str]):
    _list: list[tuple[str, str]]
    def __init__(
        self,
        defaults: Mapping[str, str | Iterable[str]]
        | Iterable[tuple[str, str]]
        | None = None,
    ) -> None: ...
    @overload
    def __getitem__(self, key: str) -> str: ...
    @overload
    def __getitem__(self, key: int) -> tuple[str, str]: ...
    @overload
    def __getitem__(self, key: slice) -> Headers: ...
    @overload
    def __getitem__(self, key: str, _get_mode: Literal[True] = ...) -> str: ...
    def __eq__(self, other: object) -> bool: ...
    @overload  # type: ignore
    def get(self, key: str, default: str) -> str: ...
    @overload
    def get(self, key: str, default: str | None = None) -> str | None: ...
    @overload
    def get(
        self, key: str, default: T | None = None, type: Callable[[str], T] = ...
    ) -> T | None: ...
    @overload
    def getlist(self, key: str) -> list[str]: ...
    @overload
    def getlist(self, key: str, type: Callable[[str], T]) -> list[T]: ...
    def get_all(self, name: str) -> list[str]: ...
    def items(  # type: ignore
        self, lower: bool = False
    ) -> Iterator[tuple[str, str]]: ...
    def keys(self, lower: bool = False) -> Iterator[str]: ...  # type: ignore
    def values(self) -> Iterator[str]: ...  # type: ignore
    def extend(
        self,
        *args: Mapping[str, str | Iterable[str]] | Iterable[tuple[str, str]],
        **kwargs: str | Iterable[str],
    ) -> None: ...
    @overload
    def __delitem__(self, key: str | int | slice) -> None: ...
    @overload
    def __delitem__(self, key: str, _index_operation: Literal[False]) -> None: ...
    def remove(self, key: str) -> None: ...
    @overload  # type: ignore
    def pop(self, key: str, default: str | None = None) -> str: ...
    @overload
    def pop(
        self, key: int | None = None, default: tuple[str, str] | None = None
    ) -> tuple[str, str]: ...
    def popitem(self) -> tuple[str, str]: ...
    def __contains__(self, key: str) -> bool: ...  # type: ignore
    def has_key(self, key: str) -> bool: ...
    def __iter__(self) -> Iterator[tuple[str, str]]: ...  # type: ignore
    def add(self, _key: str, _value: str, **kw: str) -> None: ...
    def _validate_value(self, value: str) -> None: ...
    def add_header(self, _key: str, _value: str, **_kw: str) -> None: ...
    def clear(self) -> None: ...
    def set(self, _key: str, _value: str, **kw: str) -> None: ...
    def setlist(self, key: str, values: Iterable[str]) -> None: ...
    def setdefault(self, key: str, default: str) -> str: ...
    def setlistdefault(self, key: str, default: Iterable[str]) -> None: ...
    @overload
    def __setitem__(self, key: str, value: str) -> None: ...
    @overload
    def __setitem__(self, key: int, value: tuple[str, str]) -> None: ...
    @overload
    def __setitem__(self, key: slice, value: Iterable[tuple[str, str]]) -> None: ...
    @overload
    def update(
        self, __m: SupportsKeysAndGetItem[str, str], **kwargs: str | Iterable[str]
    ) -> None: ...
    @overload
    def update(
        self, __m: Iterable[tuple[str, str]], **kwargs: str | Iterable[str]
    ) -> None: ...
    @overload
    def update(self, **kwargs: str | Iterable[str]) -> None: ...
    def to_wsgi_list(self) -> list[tuple[str, str]]: ...
    def copy(self) -> Headers: ...
    def __copy__(self) -> Headers: ...

class EnvironHeaders(ImmutableHeadersMixin, Headers):
    environ: WSGIEnvironment
    def __init__(self, environ: WSGIEnvironment) -> None: ...
    def __eq__(self, other: object) -> bool: ...
    def __getitem__(  # type: ignore
        self, key: str, _get_mode: Literal[False] = False
    ) -> str: ...
    def __iter__(self) -> Iterator[tuple[str, str]]: ...  # type: ignore
    def copy(self) -> NoReturn: ...
