from collections.abc import Sequence
from typing import ClassVar, Self

# Repeat submodule name to make it public
from . import gamut as gamut
from . import spectrum as spectrum
from . import style as style
from . import termco as termco
from . import theme as theme


class ColorSpace:
    """A color space."""
    Srgb: ClassVar[ColorSpace] = ...
    LinearSrgb: ClassVar[ColorSpace] = ...
    DisplayP3: ClassVar[ColorSpace] = ...
    LinearDisplayP3: ClassVar[ColorSpace] = ...
    Rec2020: ClassVar[ColorSpace] = ...
    LinearRec2020: ClassVar[ColorSpace] = ...
    Oklab: ClassVar[ColorSpace] = ...
    Oklch: ClassVar[ColorSpace] = ...
    Oklrab: ClassVar[ColorSpace] = ...
    Oklrch: ClassVar[ColorSpace] = ...
    Xyz: ClassVar[ColorSpace] = ...
    XyzD50: ClassVar[ColorSpace] = ...

    def is_xyz(self) -> bool: ...
    def is_rgb(self) -> bool: ...
    def is_polar(self) -> bool: ...
    def is_ok(self) -> bool: ...
    def is_bounded(self) -> bool: ...
    def gamut(self, segment_size: int) -> None | gamut.GamutTraversal: ...
    def __hash__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __str__(self) -> str: ...


class OkVersion:
    """The version of the Oklab color space."""
    Original: ClassVar[OkVersion] = ...
    Revised: ClassVar[OkVersion] = ...

    def cartesian_space(self) -> ColorSpace: ...
    def polar_space(self) -> ColorSpace: ...
    def __hash__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...


# ======================================================================================


class Color:
    """High-resolution colors."""
    def __new__(
        cls, space: ColorSpace, coordinates: Sequence[float]
    ) -> Self:
        """
        Create a new color with the color space and coordinates. The coordinates
        must be a sequence with exactly three elements.
        """
        ...
    @staticmethod
    def parse(s: str) -> Color: ...
    @staticmethod
    def srgb(r: float, g: float, b: float) -> Color: ...
    @staticmethod
    def p3(r: float, g: float, b: float) -> Color: ...
    @staticmethod
    def oklab(l: float, a: float, b: float) -> Color: ...
    @staticmethod
    def oklrab(lr: float, a: float, b: float) -> Color: ...
    @staticmethod
    def oklch(l: float, c: float, h: float) -> Color: ...
    @staticmethod
    def oklrch(lr: float, c: float, h: float) -> Color: ...
    @staticmethod
    def from_24bit(r: int, g: int, b: int) -> Color: ...
    def is_default(self) -> bool: ...
    def is_achromatic(self) -> bool: ...
    def is_achromatic_threshold(self, threshold: float) -> bool: ...
    def space(self) -> ColorSpace: ...
    def coordinates(self) -> list[float]: ...
    def normalize(self) -> Self: ...
    def hue_chroma(self) -> tuple[float, float]: ...
    def xy_chromaticity(self) -> tuple[float, float]: ...
    def uv_prime_chromaticity(self) -> tuple[float, float]: ...
    def to(self, target: ColorSpace) -> Self: ...
    def in_gamut(self) -> bool: ...
    def clip(self) -> Self: ...
    def to_gamut(self) -> Self: ...
    def distance(self, other: Self, version: OkVersion) -> float: ...
    def interpolate(
        self,
        color: Self,
        interpolation_space: ColorSpace,
        interpolation_strategy: HueInterpolation,
    ) -> Interpolator: ...
    def lighten(self, factor: float) -> Self: ...
    def darken(self, factor: float) -> Self: ...
    def contrast_against(self, background: Self) -> float: ...
    def use_black_text(self) -> bool: ...
    def use_black_background(self) -> bool: ...
    def __hash__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __len__(self) -> int: ...
    def __getitem__(self, index: int) -> float: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def to_24bit(self) -> bytes: ...
    def to_hex_format(self) -> str: ...


class HueInterpolation:
    """The rule for deciding how to interpolate hues."""
    Shorter: ClassVar[HueInterpolation] = ...
    Longer: ClassVar[HueInterpolation] = ...
    Increasing: ClassVar[HueInterpolation] = ...
    Decreasing: ClassVar[HueInterpolation] = ...

    def __hash__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...


class Interpolator:
    """A color interpolator."""
    def __new__(
        cls,
        color1: Color,
        color2: Color,
        space: ColorSpace,
        strategy: HueInterpolation
    ) -> Self: ...
    def at(self, fraction: float) -> Color: ...


def close_enough(f1: float, f2: float) -> bool: ...


class Translator:
    """A class for translating between terminal and high-resolution colors."""
    def __new__(cls, version: OkVersion, theme: theme.Theme) -> Self: ...
    def __repr__(self) -> str: ...

    # Interrogate the color theme
    def is_dark_theme(self) -> bool: ...

    # Translate terminal to high-resolution colors
    def resolve(
        self,
        color: (
            int | termco.AnsiColor | termco.EmbeddedRgb | termco.GrayGradient |
            termco.EightBitColor | termco.Rgb | Color | termco.Colorant
        ),
    ) -> Color: ...
    def resolve_all(
        self,
        color: (
            int | termco.AnsiColor | termco.EmbeddedRgb | termco.GrayGradient |
            termco.EightBitColor | termco.Rgb | Color | termco.Colorant
        ),
        layer: style.Layer,
    ) -> Color: ...

    # Translate high-resolution to ANSI colors
    def to_ansi(self, color: Color) -> Color: ...
    def supports_hue_lightness(self) -> bool: ...
    def to_ansi_hue_lightness(self, color: Color) -> None | termco.AnsiColor: ...
    def to_closest_ansi(self, color: Color) -> termco.AnsiColor: ...
    def to_ansi_rgb(self, color: Color) -> termco.AnsiColor: ...

    # Translate high-resolution to 8-bit colors
    def to_closest_8bit(self, color: Color) -> termco.EightBitColor: ...
    def to_closest_8bit_with_ansi(self, color: Color) -> termco.EightBitColor: ...

    # Cap terminal colors
    def cap_hires(self, color: Color, fidelity: style.Fidelity) -> None | termco.Colorant: ...
    def cap_colorant(self, color: termco.Colorant, fidelity: style.Fidelity) -> None | termco.Colorant: ...
    def cap(
        self,
        color: (
            int | termco.AnsiColor | termco.EmbeddedRgb | termco.GrayGradient |
            termco.EightBitColor | termco.Rgb | Color | termco.Colorant
        ),
        fidelity: style.Fidelity,
    ) -> None | termco.Colorant: ...
