from _typeshed import OpenBinaryMode, OpenTextMode
from collections.abc import Callable, Mapping
from typing import IO, Any, AnyStr, TypedDict, type_check_only

from ..extractor.common import _InfoDict
from ..utils._utils import NO_DEFAULT, Namespace
from ..YoutubeDL import YoutubeDL

@type_check_only
class _FileDownloaderParams(TypedDict):
    buffersize: int
    continuedl: bool
    external_downloader_args: dict[str, list[str]] | list[str] | None
    file_access_retries: int
    hls_use_mpegts: bool
    http_chunk_size: int | None
    max_filesize: int | None
    min_filesize: int | None
    nopart: bool
    noprogress: bool
    noresizebuffer: bool
    progress_delta: float | None
    progress_template: dict[str, str]
    quiet: bool
    ratelimit: int | None
    retries: int
    retry_sleep_functions: dict[str, Callable[..., object]]
    test: bool
    throttledratelimit: int | None
    updatetime: bool
    verbose: bool
    xattr_set_filesize: bool

class FileDownloader:
    params: _FileDownloaderParams | None
    def __init__(self, ydl: YoutubeDL, params: _FileDownloaderParams) -> None: ...
    def to_screen(self, message: str, skip_eol: bool = False, quiet: bool | None = None, only_once: bool = False) -> None: ...
    @property
    def FD_NAME(cls) -> str: ...
    @staticmethod
    def format_seconds(seconds: int | None) -> str: ...
    @classmethod
    def format_eta(cls, seconds: int | None) -> str: ...
    @staticmethod
    def calc_percent(byte_counter: float, data_len: float | None) -> float: ...
    @staticmethod
    def format_percent(percent: float | None) -> str: ...
    @classmethod
    def calc_eta(
        cls,
        start_or_rate: int | None,
        now_or_remaining: float | None,
        total: int | type[NO_DEFAULT] = ...,
        current: int | type[NO_DEFAULT] = ...,
    ) -> float | int | None: ...
    @staticmethod
    def calc_speed(start: float, now: float, bytes: int) -> float | None: ...
    @staticmethod
    def format_speed(speed: int | None) -> str: ...
    @staticmethod
    def format_retries(retries: int) -> float | int: ...
    @staticmethod
    def filesize_or_none(unencoded_filename: AnyStr) -> int | None: ...
    @staticmethod
    def best_block_size(elapsed_time: float, bytes: int) -> int: ...
    def slow_down(self, start_time: float, now: float, byte_counter: int) -> None: ...
    def temp_name(self, filename: str) -> str: ...
    def undo_temp_name(self, filename: str) -> str: ...
    def ytdl_filename(self, filename: str) -> str: ...
    # Wrapper that can accept arbitrary function.
    def wrap_file_access(action: str, *, fatal: bool = False) -> Any: ...  # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
    def sanitize_open(self, filename: str, open_mode: OpenTextMode | OpenBinaryMode) -> tuple[IO[Any], str]: ...
    def try_remove(self, filename: str) -> None: ...
    def try_rename(self, old_filename: str, new_filename: str) -> None: ...
    def try_utime(self, filename: str, last_modified_hdr: str | None) -> int | None: ...
    def report_destination(self, filename: str) -> None: ...
    ProgressStyles: Namespace
    def report_progress(self, s: Mapping[str, Any]) -> None: ...
    def report_resuming_byte(self, resume_len: int) -> None: ...
    def report_retry(
        self, err: str, count: int, retries: int, frag_index: int | type[NO_DEFAULT] = ..., fatal: bool = True
    ) -> None: ...
    def report_unable_to_resume(self) -> None: ...
    @staticmethod
    def supports_manifest(manifest: str) -> bool: ...
    def download(self, filename: str, info_dict: _InfoDict, subtitle: bool = False) -> bool: ...
    def real_download(self, filename: str, info_dict: _InfoDict) -> bool | None: ...
    def add_progress_hook(self, ph: Callable[[str], object]) -> None: ...
