from collections import OrderedDict
from datetime import datetime
from typing import (Any, Callable, Dict, Iterator, List, Optional, Tuple, Type,
                    Union)
from unittest.case import TestCase
from uuid import UUID

from django.contrib.sitemaps import GenericSitemap
from django.core.files.uploadedfile import InMemoryUploadedFile, UploadedFile
from django.db.models.base import Model
from django.db.models.expressions import Combinable
from django.test.testcases import SerializeMixin
from django.test.utils import LoggingCaptureMixin
from django.urls.converters import IntConverter, StringConverter


class OrderedSet:
    dict: collections.OrderedDict = ...
    def __init__(
        self,
        iterable: Optional[
            Union[
                List[Tuple[str, str]],
                List[datetime],
                List[Combinable],
                List[int],
                List[str],
                List[UUID],
                OrderedDict,
            ]
        ] = ...,
    ) -> None: ...
    def add(
        self,
        item: Union[
            Type[Model], SerializeMixin, LoggingCaptureMixin, int, TestCase
        ],
    ) -> None: ...
    def remove(self, item: Any) -> None: ...
    def discard(self, item: Any) -> None: ...
    def __iter__(self): ...
    def __contains__(self, item: Any): ...
    def __bool__(self) -> bool: ...
    def __len__(self) -> int: ...

class MultiValueDictKeyError(KeyError): ...

class MultiValueDict(dict):
    def __init__(
        self,
        key_to_list_mapping: Union[
            Dict[str, List[List[Any]]],
            Dict[str, List[int]],
            Dict[str, List[str]],
            List[Tuple[str, Union[List[List[Any]], List[str]]]],
            Tuple,
        ] = ...,
    ) -> None: ...
    def __getitem__(
        self, key: str
    ) -> Optional[Union[List[str], UploadedFile, str]]: ...
    def __setitem__(
        self, key: str, value: Optional[Union[int, str]]
    ) -> None: ...
    def __copy__(self) -> MultiValueDict: ...
    def __deepcopy__(self, memo: Any): ...
    def get(
        self, key: str, default: Optional[Union[int, str]] = ...
    ) -> Optional[Union[InMemoryUploadedFile, int, str]]: ...
    def getlist(
        self, key: Optional[Union[Callable, str]], default: Any = ...
    ) -> Any: ...
    def setlist(self, key: Union[Callable, str], list_: List[str]) -> None: ...
    def setdefault(self, key: str, default: str = ...) -> str: ...
    def setlistdefault(
        self, key: Union[Callable, str], default_list: None = ...
    ) -> Union[
        List[
            Tuple[
                List[Tuple[str, List[str]]], str, Dict[str, str], Dict[Any, Any]
            ]
        ],
        List[UploadedFile],
        List[str],
    ]: ...
    def appendlist(
        self,
        key: Union[Callable, str],
        value: Union[
            Tuple[
                List[Tuple[str, List[str]]],
                str,
                Dict[str, Dict[str, GenericSitemap]],
                Dict[str, Union[IntConverter, StringConverter]],
            ],
            UploadedFile,
            str,
        ],
    ) -> None: ...
    def items(self) -> Iterator[Tuple[str, InMemoryUploadedFile]]: ...
    def lists(self): ...
    def values(self) -> Iterator[str]: ...
    def copy(self) -> MultiValueDict: ...
    def update(self, *args: Any, **kwargs: Any) -> None: ...
    def dict(self) -> Dict[str, str]: ...

class ImmutableList(tuple):
    warning: str = ...
    def __new__(
        cls: Type[ImmutableList], *args: Any, warning: str = ..., **kwargs: Any
    ) -> ImmutableList: ...
    def complain(self, *wargs: Any, **kwargs: Any) -> Any: ...
    __delitem__: Any = ...
    __delslice__: Any = ...
    __iadd__: Any = ...
    __imul__: Any = ...
    __setitem__: Any = ...
    __setslice__: Any = ...
    append: Any = ...
    extend: Any = ...
    insert: Any = ...
    pop: Any = ...
    remove: Any = ...
    sort: Any = ...
    reverse: Any = ...

class DictWrapper(dict):
    func: Callable = ...
    prefix: str = ...
    def __init__(
        self, data: Dict[str, str], func: Callable, prefix: str
    ) -> None: ...
    def __getitem__(self, key: str) -> Optional[Union[int, str]]: ...
