from collections.abc import Iterable
from dataclasses import dataclass
from numbers import Integral
import os
from pathlib import Path
from typing import Any, Final, Literal

from matplotlib._afm import AFM
from matplotlib import ft2font

font_scalings: dict[str | None, float]
stretch_dict: dict[str, int]
weight_dict: dict[str, int]
font_family_aliases: set[str]
MSFolders: str
MSFontDirectories: list[str]
MSUserFontDirectories: list[str]
X11FontDirectories: list[str]
OSXFontDirectories: list[str]

def _normalize_weight(weight: str | Integral) -> Integral: ...
def get_fontext_synonyms(fontext: str) -> list[str]: ...
def list_fonts(directory: str, extensions: Iterable[str]) -> list[str]: ...
def win32FontDirectory() -> str: ...
def _get_fontconfig_fonts() -> list[Path]: ...
def _get_font_alt_names(
    font: ft2font.FT2Font, primary_name: str
) -> list[tuple[str, int]]: ...
def findSystemFonts(
    fontpaths: Iterable[str | os.PathLike] | None = ..., fontext: Literal['ttf', 'afm'] = ...
) -> list[str]: ...

class FontPath(str):
    __match_args__: Final[tuple[str, ...]]
    def __new__(cls: type[str], path: str, face_index: int) -> FontPath: ...
    @property
    def path(self) -> str: ...
    @property
    def face_index(self) -> int: ...
    def _as_tuple(self) -> tuple[str, int]: ...
    def __eq__(self, other: Any) -> bool: ...
    def __ne__(self, other: Any) -> bool: ...
    def __lt__(self, other: Any) -> bool: ...
    def __gt__(self, other: Any) -> bool: ...
    def __hash__(self) -> int: ...
    def __repr__(self) -> str: ...

@dataclass
class FontEntry:
    fname: str = ...
    index: int = ...
    name: str = ...
    style: str = ...
    variant: str = ...
    weight: str | int = ...
    stretch: str = ...
    size: str = ...
    def _repr_html_(self) -> str: ...
    def _repr_png_(self) -> bytes: ...

def ttfFontProperty(font: ft2font.FT2Font) -> FontEntry: ...
def afmFontProperty(fontpath: str, font: AFM) -> FontEntry: ...

class FontProperties:
    def __init__(
        self,
        family: str | Iterable[str] | None = ...,
        style: Literal["normal", "italic", "oblique"] | None = ...,
        variant: Literal["normal", "small-caps"] | None = ...,
        weight: int | str | None = ...,
        stretch: int | str | None = ...,
        size: float | str | None = ...,
        fname: str | os.PathLike | None = ...,
        math_fontfamily: str | None = ...,
    ) -> None: ...
    def __hash__(self) -> int: ...
    def __copy__(self) -> FontProperties: ...
    def __eq__(self, other: object) -> bool: ...
    def get_family(self) -> list[str]: ...
    def get_name(self) -> str: ...
    def get_style(self) -> Literal["normal", "italic", "oblique"]: ...
    def get_variant(self) -> Literal["normal", "small-caps"]: ...
    def get_weight(self) -> int | str: ...
    def get_stretch(self) -> int | str: ...
    def get_size(self) -> float: ...
    def get_file(self) -> str | bytes | None: ...
    def get_fontconfig_pattern(self) -> dict[str, list[Any]]: ...
    def set_family(self, family: str | Iterable[str] | None) -> None: ...
    def set_style(
        self, style: Literal["normal", "italic", "oblique"] | None
    ) -> None: ...
    def set_variant(self, variant: Literal["normal", "small-caps"] | None) -> None: ...
    def set_weight(self, weight: int | str | None) -> None: ...
    def set_stretch(self, stretch: int | str | None) -> None: ...
    def set_size(self, size: float | str | None) -> None: ...
    def set_file(self, file: str | os.PathLike | None) -> None: ...
    def set_fontconfig_pattern(self, pattern: str) -> None: ...
    def get_math_fontfamily(self) -> str: ...
    def set_math_fontfamily(self, fontfamily: str | None) -> None: ...
    def copy(self) -> FontProperties: ...
    # Aliases
    set_name = set_family
    get_slant = get_style
    set_slant = set_style
    get_size_in_points = get_size

def json_dump(data: FontManager, filename: str | os.PathLike) -> None: ...
def json_load(filename: str | os.PathLike) -> FontManager: ...

class FontManager:
    __version__: str
    default_size: float | None
    defaultFamily: dict[str, str]
    afmlist: list[FontEntry]
    ttflist: list[FontEntry]
    def __init__(self, size: float | None = ..., weight: str = ...) -> None: ...
    def addfont(self, path: str | os.PathLike) -> None: ...
    @property
    def defaultFont(self) -> dict[str, str]: ...
    def get_default_weight(self) -> str: ...
    @staticmethod
    def get_default_size() -> float: ...
    def set_default_weight(self, weight: str) -> None: ...
    def score_family(
        self, families: str | list[str] | tuple[str], family2: str
    ) -> float: ...
    def score_style(self, style1: str, style2: str) -> float: ...
    def score_variant(self, variant1: str, variant2: str) -> float: ...
    def score_stretch(self, stretch1: str | int, stretch2: str | int) -> float: ...
    def score_weight(self, weight1: str | float, weight2: str | float) -> float: ...
    def score_size(self, size1: str | float, size2: str | float) -> float: ...
    def findfont(
        self,
        prop: str | FontProperties,
        fontext: Literal["ttf", "afm"] = ...,
        directory: str | os.PathLike | None = ...,
        fallback_to_default: bool = ...,
        rebuild_if_missing: bool = ...,
    ) -> FontPath: ...
    def get_font_names(self) -> list[str]: ...
    def _find_fonts_by_props(
        self,
        prop: str | FontProperties,
        fontext: Literal["ttf", "afm"] = ...,
        directory: str | os.PathLike | None = ...,
        fallback_to_default: bool = ...,
        rebuild_if_missing: bool = ...,
    ) -> list[FontPath]: ...

def is_opentype_cff_font(filename: str) -> bool: ...
def get_font(
    font_filepaths: Iterable[str | bytes | os.PathLike | FontPath] | str | bytes | os.PathLike | FontPath,
) -> ft2font.FT2Font: ...

fontManager: FontManager

def findfont(
    prop: str | FontProperties,
    fontext: Literal["ttf", "afm"] = ...,
    directory: str | os.PathLike | None = ...,
    fallback_to_default: bool = ...,
    rebuild_if_missing: bool = ...,
) -> FontPath: ...
def get_font_names() -> list[str]: ...
