from collections.abc import Callable, Iterator, MutableMapping
from typing import Any, Literal, TypeVar, overload

import matplotlib.patches as mpatches
from matplotlib.axes import Axes
from matplotlib.axis import Axis
from matplotlib.path import Path
from matplotlib.transforms import Transform
from matplotlib.typing import ColorType

class Spine(mpatches.Patch):
    axes: Axes
    spine_type: str
    axis: Axis | None
    def __init__(self, axes: Axes, spine_type: str, path: Path, **kwargs) -> None: ...
    def set_patch_arc(
        self, center: tuple[float, float], radius: float, theta1: float, theta2: float
    ) -> None: ...
    def set_patch_circle(self, center: tuple[float, float], radius: float) -> None: ...
    def set_patch_line(self) -> None: ...
    def get_patch_transform(self) -> Transform: ...
    def get_path(self) -> Path: ...
    def register_axis(self, axis: Axis) -> None: ...
    def clear(self) -> None: ...
    def set_position(
        self,
        position: Literal["center", "zero"]
        | tuple[Literal["outward", "axes", "data"], float],
    ) -> None: ...
    def get_position(
        self,
    ) -> Literal["center", "zero"] | tuple[
        Literal["outward", "axes", "data"], float
    ]: ...
    def get_spine_transform(self) -> Transform: ...
    def set_bounds(self, low: float | None = ..., high: float | None = ...) -> None: ...
    def get_bounds(self) -> tuple[float, float]: ...

    _T = TypeVar("_T", bound=Spine)
    @classmethod
    def linear_spine(
        cls: type[_T],
        axes: Axes,
        spine_type: Literal["left", "right", "bottom", "top"],
        **kwargs
    ) -> _T: ...
    @classmethod
    def arc_spine(
        cls: type[_T],
        axes: Axes,
        spine_type: Literal["left", "right", "bottom", "top"],
        center: tuple[float, float],
        radius: float,
        theta1: float,
        theta2: float,
        **kwargs
    ) -> _T: ...
    @classmethod
    def circular_spine(
        cls: type[_T], axes: Axes, center: tuple[float, float], radius: float, **kwargs
    ) -> _T: ...
    def set_color(self, c: ColorType | None) -> None: ...

class SpinesProxy:
    def __init__(self, spine_dict: dict[str, Spine]) -> None: ...
    def __getattr__(self, name: str) -> Callable[..., None]: ...
    def __dir__(self) -> list[str]: ...

class Spines(MutableMapping[str, Spine]):
    def __init__(self, **kwargs: Spine) -> None: ...
    @classmethod
    def from_dict(cls, d: dict[str, Spine]) -> Spines: ...
    def __getattr__(self, name: str) -> Spine: ...
    @overload
    def __getitem__(self, key: str) -> Spine: ...
    @overload
    def __getitem__(self, key: list[str]) -> SpinesProxy: ...
    @overload
    def __getitem__(self, key: slice) -> SpinesProxy: ...
    def __setitem__(self, key: str, value: Spine) -> None: ...
    def __delitem__(self, key: str) -> None: ...
    def __iter__(self) -> Iterator[str]: ...
    def __len__(self) -> int: ...
