import json
from dataclasses import dataclass
from functools import lru_cache
from pathlib import PosixPath
from typing import Literal

from matplotlib.ft2font import FT2Font

from ._afm import AFM
from ._typing import *

font_scalings = ...
stretch_dict = ...
weight_dict = ...

font_family_aliases = ...
MSFolders = ...
MSFontDirectories = ...
MSUserFontDirectories = ...
X11FontDirectories = ...
OSXFontDirectories = ...

def get_fontext_synonyms(fontext): ...
def list_fonts(directory, extensions): ...
def win32FontDirectory(): ...
def win32InstalledFonts(directory=..., fontext=...): ...
def get_fontconfig_fonts(fontext=...): ...
def findSystemFonts(fontpaths=..., fontext=...): ...
@dataclass
class FontEntry:
    fname: str = ...
    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) -> FontEntry: ...
def afmFontProperty(fontpath, font: AFM) -> FontEntry: ...

class FontProperties:
    def __init__(
        self,
        family: list[str] | str | Literal["sans-serif", "serif", "cursive", "fantasy", "monospace"] = ...,
        style: Literal["normal", "italic", "oblique"] = ...,
        variant: Literal["normal", "small-caps"] = ...,
        weight: (
            int
            | Literal[
                "ultralight",
                "light",
                "normal",
                "regular",
                "book",
                "medium",
                "roman",
                "semibold",
                "demibold",
                "demi",
                "bold",
                "heavy",
                "extra bold",
                "black",
            ]
        ) = ...,
        stretch: (
            int
            | Literal[
                "ultra-condensed",
                "extra-condensed",
                "condensed",
                "semi-condensed",
                "normal",
                "semi-expanded",
                "expanded",
                "extra-expanded",
                "ultra-expanded",
            ]
        ) = ...,
        size: float | Literal["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"] = ...,
        fname: PosixPath | None = ...,
        math_fontfamily: Literal["dejavusans", "dejavuserif", "cm", "stix", "stixsans", "custom"] = ...,
    ) -> None: ...
    def __hash__(self) -> int: ...
    def __eq__(self, other: FontProperties) -> bool: ...
    def get_family(self) -> list[str]: ...
    def get_name(self) -> str: ...
    def get_style(self) -> str: ...
    def get_variant(self) -> str: ...
    def get_weight(self) -> str: ...
    def get_stretch(self) -> str: ...
    def get_size(self) -> float: ...
    def get_file(self) -> str | None: ...
    def get_fontconfig_pattern(self) -> str: ...
    def set_family(
        self,
        family: str | list[str] | Literal["sans-serif", "serif", "cursive", "fantasy", "monospace"],
    ) -> None: ...
    def set_style(self, style: Literal["normal", "italic", "oblique"]) -> None: ...
    def set_variant(self, variant: Literal["normal", "small-caps"]) -> None: ...
    def set_weight(
        self,
        weight: (
            int
            | Literal[
                "ultralight",
                "light",
                "normal",
                "regular",
                "book",
                "medium",
                "roman",
                "semibold",
                "demibold",
                "demi",
                "bold",
                "heavy",
                "extra bold",
                "black",
            ]
        ),
    ) -> None: ...
    def set_stretch(
        self,
        stretch: (
            int
            | Literal[
                "ultra-condensed",
                "extra-condensed",
                "condensed",
                "semi-condensed",
                "normal",
                "semi-expanded",
                "expanded",
                "extra-expanded",
                "ultra-expanded",
            ]
        ),
    ) -> None: ...
    def set_size(
        self,
        size: float | Literal["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"],
    ) -> None: ...
    def set_file(self, file: PosixPath | None) -> None: ...
    def set_fontconfig_pattern(self, pattern: str) -> None: ...
    def get_math_fontfamily(self) -> str: ...
    def set_math_fontfamily(
        self,
        fontfamily: Literal["dejavusans", "dejavuserif", "cm", "stix", "stixsans", "custom"],
    ) -> None: ...
    def copy(self) -> FontProperties: ...
    set_name = ...
    get_slant = ...
    set_slant = ...
    get_size_in_points = ...

class _JSONEncoder(json.JSONEncoder):
    def default(self, o): ...

def json_dump(data, filename): ...
def json_load(filename: PosixPath) -> FontManager: ...

class FontManager:
    def __init__(self, size=..., weight=...) -> None: ...
    def addfont(self, path: str | PathLike): ...
    @property
    def defaultFont(self): ...
    def get_default_weight(self): ...
    @staticmethod
    def get_default_size() -> float: ...
    def set_default_weight(
        self,
        weight: (
            int
            | Literal[
                "ultralight",
                "light",
                "normal",
                "regular",
                "book",
                "medium",
                "roman",
                "semibold",
                "demibold",
                "demi",
                "bold",
                "heavy",
                "extra bold",
                "black",
            ]
        ),
    ): ...
    def score_family(self, families: list[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, stretch2: str) -> float: ...
    def score_weight(self, weight1: str, weight2: int) -> float: ...
    def score_size(self, size1: float, size2: str) -> float: ...
    def findfont(
        self,
        prop: FontProperties | str,
        fontext: Literal["ttf", "afm"] = ...,
        directory: str = ...,
        fallback_to_default: bool = ...,
        rebuild_if_missing: bool = ...,
    ) -> str: ...
    def get_font_names(self) -> list: ...

@lru_cache
def is_opentype_cff_font(filename): ...
def get_font(filename, hinting_factor=...): ...

fontManager = ...
findfont = ...
get_font_names = ...
