import enum
import functools
import sys
from _typeshed import Incomplete
from typing import Literal

from .font_manager import FontProperties
from .mathtext import MathtextBackend

# tkinter.tix was removed from Python 3.13
# Recent matplotlib versions define HList in this module
if sys.version_info >= (3, 13):
    HList = Incomplete
else:
    from tkinter.tix import HList

def get_unicode_index(symbol: str, math: bool = True) -> int: ...

class Fonts:
    def __init__(self, default_font_prop: FontProperties, mathtext_backend: MathtextBackend) -> None: ...
    def get_kern(
        self,
        font1,
        fontclass1,
        sym1: str,
        fontsize1: float,
        font2,
        fontclass2: float,
        sym2: str,
        fontsize2: float,
        dpi: float,
    ) -> float: ...
    def get_metrics(self, font: str, font_class: str, sym: str, fontsize: float, dpi: float) -> object: ...
    def render_glyph(self, ox: float, oy: float, font, font_class, sym, fontsize: float, dpi: float) -> None: ...
    def render_rect_filled(self, x1: float, y1: float, x2: float, y2: float) -> None: ...
    def get_xheight(self, font, fontsize: float, dpi: float) -> float: ...
    def get_underline_thickness(self, font, fontsize: float, dpi: float) -> float: ...
    def get_used_characters(self): ...
    def get_sized_alternatives_for_symbol(self, fontname, sym) -> list[tuple]: ...

class TruetypeFonts(Fonts):
    def __init__(self, default_font_prop, mathtext_backend) -> None: ...
    def get_xheight(self, fontname, fontsize: float, dpi: float) -> float: ...
    def get_underline_thickness(self, font, fontsize: float, dpi: float) -> float: ...
    def get_kern(
        self,
        font1,
        fontclass1,
        sym1: str,
        fontsize1: float,
        font2,
        fontclass2: float,
        sym2: str,
        fontsize2: float,
        dpi: float,
    ): ...

class BakomaFonts(TruetypeFonts):
    def __init__(self, *args, **kwargs) -> None: ...
    def get_sized_alternatives_for_symbol(self, fontname, sym) -> list[tuple]: ...

class UnicodeFonts(TruetypeFonts):
    def __init__(self, *args, **kwargs) -> None: ...
    def get_sized_alternatives_for_symbol(self, fontname, sym) -> list[tuple]: ...

class DejaVuFonts(UnicodeFonts):
    def __init__(self, *args, **kwargs) -> None: ...

class DejaVuSerifFonts(DejaVuFonts): ...
class DejaVuSansFonts(DejaVuFonts): ...

class StixFonts(UnicodeFonts):
    def __init__(self, *args, **kwargs) -> None: ...
    @functools.lru_cache
    def get_sized_alternatives_for_symbol(self, fontname, sym) -> list[tuple]: ...

class StixSansFonts(StixFonts): ...

SHRINK_FACTOR: float = ...
NUM_SIZE_LEVELS: int = ...

class FontConstantsBase:
    script_space: float = ...
    subdrop: float = ...
    sup1: float = ...
    sub1: float = ...
    sub2: float = ...
    delta: float = ...
    delta_slanted: float = ...
    delta_integral: float = ...

class ComputerModernFontConstants(FontConstantsBase):
    script_space: float = ...
    subdrop: float = ...
    sup1: float = ...
    sub1: float = ...
    sub2: float = ...
    delta: float = ...
    delta_slanted: float = ...
    delta_integral: float = ...

class STIXFontConstants(FontConstantsBase):
    script_space: float = ...
    sup1: float = ...
    sub2: float = ...
    delta: float = ...
    delta_slanted: float = ...
    delta_integral: float = ...

class STIXSansFontConstants(FontConstantsBase):
    script_space: float = ...
    sup1: float = ...
    delta_slanted: float = ...
    delta_integral: float = ...

class DejaVuSerifFontConstants(FontConstantsBase): ...
class DejaVuSansFontConstants(FontConstantsBase): ...

class Node:
    def __init__(self) -> None: ...
    def get_kerning(self, next) -> float: ...
    def shrink(self) -> None: ...
    def render(self, x: float, y: float) -> None: ...

class Box(Node):
    def __init__(self, width: float, height: float, depth: float) -> None: ...
    def shrink(self) -> None: ...
    def render(self, x1: float, y1: float, x2: float, y2: float) -> None: ...

class Vbox(Box):
    def __init__(self, height: float, depth: float) -> None: ...

class Hbox(Box):
    def __init__(self, width: float) -> None: ...

class Char(Node):
    def __init__(self, c, state) -> None: ...
    def is_slanted(self) -> bool: ...
    def get_kerning(self, next) -> float: ...
    def render(self, x: float, y: float) -> None: ...
    def shrink(self) -> None: ...

class Accent(Char):
    def shrink(self) -> None: ...
    def render(self, x: float, y: float) -> None: ...

class List(Box):
    def __init__(self, elements) -> None: ...
    def shrink(self) -> None: ...

class Hlist(List):
    def __init__(
        self,
        elements,
        w: float = 0,
        m: Literal["exactly", "additional"] = "additional",
        do_kern: bool = True,
    ) -> None: ...
    def kern(self) -> None: ...
    def hpack(self, w: float = 0, m: Literal["exactly", "additional"] = "additional") -> None: ...

class Vlist(List):
    def __init__(self, elements, h=0, m=...) -> None: ...
    def vpack(
        self,
        h: float = ...,
        m: Literal["exactly", "additional"] = "additional",
        l: float = ...,
    ) -> None: ...

class Rule(Box):
    def __init__(self, width: float, height: float, depth: float, state) -> None: ...
    def render(self, x: float, y: float, w: float, h: float) -> None: ...

class Hrule(Rule):
    def __init__(self, state, thickness=...) -> None: ...

class Vrule(Rule):
    def __init__(self, state) -> None: ...

class Glue(Node):
    def __init__(self, glue_type) -> None: ...
    def shrink(self): ...

class HCentered(Hlist):
    def __init__(self, elements) -> None: ...

class VCentered(Vlist):
    def __init__(self, elements) -> None: ...

class Kern(Node):
    height: float = ...
    depth: float = ...
    def __init__(self, width: float) -> None: ...
    def shrink(self) -> None: ...

class AutoHeightChar(Hlist):
    def __init__(self, c, height: float, depth: float, state, always=False, factor=None) -> None: ...

class AutoWidthChar(Hlist):
    def __init__(self, c, width: float, state, always=False, char_class=Char) -> None: ...

def ship(ox, oy, box) -> None: ...
def Error(msg): ...

class ParserState:
    def __init__(self, font_output, font, font_class, fontsize: float, dpi: float) -> None: ...
    def copy(self) -> ParserState: ...
    @property
    def font(self): ...
    @font.setter
    def font(self, name: str) -> None: ...
    def get_current_underline_thickness(self) -> float: ...

def cmd(expr, args): ...

class Parser:
    class _MathStyle(enum.Enum):
        DISPLAYSTYLE = ...
        TEXTSTYLE = ...
        SCRIPTSTYLE = ...
        SCRIPTSCRIPTSTYLE = ...

    def __init__(self) -> None: ...
    def parse(self, s, fonts_object, fontsize: float, dpi: float): ...
    def get_state(self) -> ParserState: ...
    def pop_state(self) -> ParserState: ...
    def push_state(self): ...
    def main(self, s, loc, toks) -> list[HList]: ...
    def math_string(self, s, loc, toks): ...
    def math(self, s, loc, toks) -> list[HList]: ...
    def non_math(self, s, loc, toks) -> list[HList]: ...

    float_literal = ...

    def space(self, s, loc, toks) -> list[Kern]: ...
    def customspace(self, s, loc, toks) -> list[Kern]: ...
    def symbol(self, s, loc, toks) -> list: ...

    accentprefixed = ...
    def unknown_symbol(self, s, loc, toks): ...
    def accent(self, s, loc, toks) -> Vlist: ...
    def function(self, s, loc, toks) -> Hlist: ...
    def operatorname(self, s, loc, toks) -> HList: ...
    def start_group(self, s, loc, toks) -> list: ...
    def group(self, s, loc, toks) -> list[Hlist]: ...
    def required_group(self, s, loc, toks) -> Hlist: ...

    optional_group = ...
    def end_group(self, s, loc, toks) -> list: ...
    def font(self, s, loc, toks) -> list: ...
    def is_overunder(self, nucleus) -> bool: ...
    def is_dropsub(self, nucleus) -> bool: ...
    def is_slanted(self, nucleus) -> bool: ...
    def is_between_brackets(self, s, loc): ...
    def subsuper(self, s, loc, toks): ...
    def style_literal(self, s, loc, toks): ...
    def genfrac(self, s, loc, toks): ...
    def frac(self, s, loc, toks): ...
    def dfrac(self, s, loc, toks): ...
    def binom(self, s, loc, toks): ...

    overset = ...
    def sqrt(self, s, loc, toks) -> list[Hlist]: ...
    def overline(self, s, loc, toks) -> list[Hlist]: ...
    def auto_delim(self, s, loc, toks) -> Hlist: ...
