import os
import pathlib
import sys
from collections.abc import Container, Iterable, MutableSequence
from functools import partial
from typing import Any, Callable, TypeVar, overload

from _typeshed import StrPath
from typing_extensions import Self

T = TypeVar("T")

class MonitoredList(MutableSequence[T]):
    def __init__(
        self, items: Iterable[T] = (), callback: Callable[[Self], None] | None = None, type: type[T] | None = None
    ) -> None: ...
    @overload
    def __getitem__(self, index: int, /) -> T: ...
    @overload
    def __getitem__(self, index: slice, /) -> Self: ...
    @overload
    def __delitem__(self, index: int, /) -> None: ...
    @overload
    def __delitem__(self, index: slice, /) -> None: ...
    @overload
    def __setitem__(self, index: int, value: T, /) -> None: ...
    @overload
    def __setitem__(self, index: slice, value: Iterable[T], /) -> None: ...
    def insert(self, index: int, value: T) -> None: ...
    def replace(self, items: Iterable[T]) -> None: ...
    def clear(self) -> None: ...
    def __len__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __add__(self, other: object) -> Self: ...
    def __repr__(self) -> str: ...

class File(os.PathLike[str]):
    def __fspath__(self) -> str: ...
    def __reduce__(self) -> tuple[partial[Self], tuple[()]]: ...
    def __init__(self, path: StrPath | Iterable[StrPath], size: int) -> None: ...
    @property
    def size(self) -> int: ...
    def __getattr__(self, name: str) -> Any: ...
    def __str__(self) -> str: ...
    def __eq__(self, other: object) -> bool: ...
    def __hash__(self) -> int: ...
    def __gt__(self, other: object) -> bool: ...
    def __lt__(self, other: object) -> bool: ...
    def __ge__(self, other: object) -> bool: ...
    def __le__(self, other: object) -> bool: ...
    def __repr__(self) -> str: ...

class Files(MonitoredList[File]):
    def __init__(self, files: str | Iterable[str], callback: Callable[[Self], None] | None = None): ...

# There is special recognition in Mypy for `sys.platform`, not `os.name`
if sys.platform == "win32":
    PathBase = pathlib.WindowsPath
else:
    PathBase = pathlib.PosixPath

class Filepath(PathBase):
    def __eq__(self, other: object) -> bool: ...
    def __hash__(self) -> int: ...

class Filepaths(MonitoredList[Filepath]):
    def __init__(self, filepaths: str | Iterable[str], callback: Callable[[Self], None] | None = None) -> None: ...
    @overload
    def __setitem__(self, index: int, path: StrPath, /) -> None: ...
    @overload
    def __setitem__(self, index: slice, path: Iterable[StrPath], /) -> None: ...
    def insert(self, index: int, path: StrPath) -> None: ...

class URL(str):
    def __new__(cls, s: str) -> Self: ...
    def __init__(self, url: str) -> None: ...
    @property
    def scheme(self) -> str: ...
    @property
    def netloc(self) -> str: ...
    @property
    def hostname(self) -> str | None: ...
    @property
    def port(self) -> int | None: ...
    @property
    def path(self) -> str: ...
    @property
    def params(self) -> str: ...
    @property
    def query(self) -> str: ...
    @property
    def fragment(self) -> str: ...

class URLs(MonitoredList[URL]):
    def __init__(
        self,
        urls: str | Iterable[str],
        callback: Callable[[Self], None] | None = None,
        _get_known_urls: Callable[[], Container[str]] = lambda: (),
    ): ...

class Trackers(MutableSequence[URLs]):
    def __init__(self, tiers: str | Iterable[str], callback: Callable[[Self], None] | None = None) -> None: ...
    @property
    def flat(self) -> tuple[URL, ...]: ...
    @overload
    def __getitem__(self, index: int, /) -> URLs: ...
    @overload
    def __getitem__(self, index: slice, /) -> Self: ...
    @overload
    def __delitem__(self, index: int, /) -> None: ...
    @overload
    def __delitem__(self, index: slice, /) -> None: ...
    @overload
    def __setitem__(self, index: int, value: URLs, /) -> None: ...
    @overload
    def __setitem__(self, index: slice, value: Iterable[URLs], /) -> None: ...
    def insert(self, index: int, value: Iterable[str]) -> None: ...
    def replace(self, tiers: Iterable[str]) -> None: ...
    def clear(self) -> None: ...
    def __len__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __add__(self, other: str | Iterable[str]) -> Self: ...
    def __repr__(self) -> str: ...
