"""
Colour Matching Functions
=========================

Define the colour matching functions classes for the datasets from
the :mod:`colour.colorimetry.datasets.cmfs` module:

-   :class:`colour.colorimetry.LMS_ConeFundamentals`: Define support for
    *Stockman and Sharpe* *LMS* cone fundamentals colour matching functions.
-   :class:`colour.colorimetry.RGB_ColourMatchingFunctions`: Define support
    for *CIE RGB* colour matching functions.
-   :class:`colour.colorimetry.XYZ_ColourMatchingFunctions`: Define support
    for *CIE Standard Observers* *XYZ* colour matching functions.
"""

from __future__ import annotations

import typing

from colour.colorimetry import (
    MultiSpectralDistributions,
    SpectralDistribution,
    SpectralShape,
)

if typing.TYPE_CHECKING:
    from collections.abc import KeysView, ValuesView
    from colour.continuous import MultiSignals, Signal
    from colour.hints import (
        Any,
        ArrayLike,
        Sequence,
    )

from colour.utilities import is_pandas_installed

if typing.TYPE_CHECKING or is_pandas_installed():
    from pandas import DataFrame, Series  # pragma: no cover
else:  # pragma: no cover
    from unittest import mock

    DataFrame = mock.MagicMock()
    Series = mock.MagicMock()

__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "colour-developers@colour-science.org"
__status__ = "Production"

__all__ = [
    "LMS_ConeFundamentals",
    "RGB_ColourMatchingFunctions",
    "XYZ_ColourMatchingFunctions",
]


class LMS_ConeFundamentals(MultiSpectralDistributions):
    """
    Define a container for *Stockman and Sharpe* *LMS* cone fundamentals
    colour matching functions.

    Parameters
    ----------
    data
        Data to be stored in the multi-spectral distributions.
    domain
        Values to initialise the multiple
        :class:`colour.SpectralDistribution` class instances
        :attr:`colour.continuous.Signal.wavelengths` attribute with. If
        both ``data`` and ``domain`` arguments are defined, the latter will
        be used to initialise the
        :attr:`colour.continuous.Signal.wavelengths` property.
    labels
        Names to use for the :class:`colour.SpectralDistribution` class
        instances.

    Other Parameters
    ----------------
    extrapolator
        Extrapolator class type to use as extrapolating function for the
        :class:`colour.SpectralDistribution` class instances.
    extrapolator_kwargs
        Arguments to use when instantiating the extrapolating function of
        the :class:`colour.SpectralDistribution` class instances.
    interpolator
        Interpolator class type to use as interpolating function for the
        :class:`colour.SpectralDistribution` class instances.
    interpolator_kwargs
        Arguments to use when instantiating the interpolating function of
        the :class:`colour.SpectralDistribution` class instances.
    name
        Multi-spectral distributions name.
    display_labels
        Multi-spectral distributions labels for figures, default to
        :attr:`colour.colorimetry.LMS_ConeFundamentals.labels` property
        value.
    """

    def __init__(
        self,
        data: (
            ArrayLike
            | DataFrame
            | dict
            | MultiSignals
            | MultiSpectralDistributions
            | Sequence
            | Series
            | Signal
            | SpectralDistribution
            | ValuesView
            | None
        ) = None,
        domain: ArrayLike | SpectralShape | KeysView | None = None,
        labels: Sequence | None = None,  # noqa: ARG002
        **kwargs: Any,
    ) -> None:
        super().__init__(
            data,
            domain,
            labels=("l_bar", "m_bar", "s_bar"),
            display_labels=("$\\bar{l}$", "$\\bar{m}$", "$\\bar{s}$"),
            **kwargs,
        )


class RGB_ColourMatchingFunctions(MultiSpectralDistributions):
    """
    Define a container for *CIE RGB* colour matching functions.

    Parameters
    ----------
    data
        Data to be stored in the multi-spectral distributions.
    domain
        Values to initialise the multiple
        :class:`colour.SpectralDistribution` class instances
        :attr:`colour.continuous.Signal.wavelengths` attribute with. If
        both ``data`` and ``domain`` arguments are defined, the latter will
        be used to initialise the
        :attr:`colour.continuous.Signal.wavelengths` property.
    labels
        Names to use for the :class:`colour.SpectralDistribution` class
        instances.

    Other Parameters
    ----------------
    extrapolator
        Extrapolator class type to use as extrapolating function for the
        :class:`colour.SpectralDistribution` class instances.
    extrapolator_kwargs
        Arguments to use when instantiating the extrapolating function of
        the :class:`colour.SpectralDistribution` class instances.
    interpolator
        Interpolator class type to use as interpolating function for the
        :class:`colour.SpectralDistribution` class instances.
    interpolator_kwargs
        Arguments to use when instantiating the interpolating function of
        the :class:`colour.SpectralDistribution` class instances.
    name
        Multi-spectral distributions name.
    display_labels
        Multi-spectral distributions labels for figures, default to
        :attr:`colour.colorimetry.RGB_ColourMatchingFunctions.labels` property
        value.
    """

    def __init__(
        self,
        data: (
            ArrayLike
            | DataFrame
            | dict
            | MultiSignals
            | MultiSpectralDistributions
            | Sequence
            | Series
            | Signal
            | SpectralDistribution
            | ValuesView
            | None
        ) = None,
        domain: ArrayLike | SpectralShape | KeysView | None = None,
        labels: Sequence | None = None,  # noqa: ARG002
        **kwargs: Any,
    ) -> None:
        super().__init__(
            data,
            domain,
            labels=("r_bar", "g_bar", "b_bar"),
            display_labels=("$\\bar{r}$", "$\\bar{g}$", "$\\bar{b}$"),
            **kwargs,
        )


class XYZ_ColourMatchingFunctions(MultiSpectralDistributions):
    """
    Define a container for *CIE* Standard Observers *XYZ* colour matching
    functions.

    Parameters
    ----------
    data
        Data to be stored in the multi-spectral distributions.
    domain
        Values to initialise the multiple
        :class:`colour.SpectralDistribution` class instances
        :attr:`colour.continuous.Signal.wavelengths` attribute with. If
        both ``data`` and ``domain`` arguments are defined, the latter will
        be used to initialise the
        :attr:`colour.continuous.Signal.wavelengths` property.
    labels
        Names to use for the :class:`colour.SpectralDistribution` class
        instances.

    Other Parameters
    ----------------
    extrapolator
        Extrapolator class type to use as extrapolating function for the
        :class:`colour.SpectralDistribution` class instances.
    extrapolator_kwargs
        Arguments to use when instantiating the extrapolating function of
        the :class:`colour.SpectralDistribution` class instances.
    interpolator
        Interpolator class type to use as interpolating function for the
        :class:`colour.SpectralDistribution` class instances.
    interpolator_kwargs
        Arguments to use when instantiating the interpolating function of
        the :class:`colour.SpectralDistribution` class instances.
    name
        Multi-spectral distributions name.
    display_labels
        Multi-spectral distributions labels for figures, default to
        :attr:`colour.colorimetry.XYZ_ColourMatchingFunctions.labels` property
        value.
    """

    def __init__(
        self,
        data: (
            ArrayLike
            | DataFrame
            | dict
            | MultiSignals
            | MultiSpectralDistributions
            | Sequence
            | Series
            | Signal
            | SpectralDistribution
            | ValuesView
            | None
        ) = None,
        domain: ArrayLike | SpectralShape | KeysView | None = None,
        labels: Sequence | None = None,  # noqa: ARG002
        **kwargs: Any,
    ) -> None:
        super().__init__(
            data,
            domain,
            labels=("x_bar", "y_bar", "z_bar"),
            display_labels=("$\\bar{x}$", "$\\bar{y}$", "$\\bar{z}$"),
            **kwargs,
        )
