# vim: set et sw=4 sts=4 fileencoding=utf-8:
#
# The colorzero color library
# Copyright (c) 2016-2018 Dave Jones <dave@waveform.org.uk>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the copyright holder nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

"Define the tuples used to represent various color systems."

from __future__ import (
    unicode_literals,
    print_function,
    division,
    absolute_import,
)

from collections import namedtuple, OrderedDict

from .attr import Red, Green, Blue, Hue, Lightness, Saturation, Luma


class RGB(tuple):
    "Named tuple representing red, green, and blue."
    # NOTE: This source mostly generated by namedtuple(..., verbose=True)

    __slots__ = ()

    _fields = ('r', 'g', 'b')

    def __new__(cls, r, g, b):
        return tuple.__new__(cls, (r, g, b))

    def _replace(self, **kw):
        "Return a new RGB object replacing specified fields with new values"
        # pylint: disable=bad-builtin
        result = tuple.__new__(RGB, map(kw.pop, 'rgb', self))
        if kw:
            raise ValueError('Got unexpected field names: %r' % list(kw))
        return result

    def __repr__(self):
        "Return a nicely formatted representation string"
        return self.__class__.__name__ + '(r=%r, g=%r, b=%r)' % self

    def _asdict(self):
        "Return a new OrderedDict which maps field names to their values."
        return OrderedDict(zip(self._fields, self))

    def __getnewargs__(self):
        "Return self as a plain tuple.  Used by copy and pickle."
        return tuple(self)

    @property
    def r(self):
        "Return the red value as a :class:`Red` instance"
        # pylint: disable=invalid-name
        return Red(self[0])

    @property
    def red(self):
        "Return the red value as a :class:`Red` instance"
        return Red(self[0])

    @property
    def g(self):
        "Return the green value as a :class:`Green` instance"
        # pylint: disable=invalid-name
        return Green(self[1])

    @property
    def green(self):
        "Return the green value as a :class:`Green` instance"
        return Green(self[1])

    @property
    def b(self):
        "Return the blue value as a :class:`Blue` instance"
        # pylint: disable=invalid-name
        return Blue(self[2])

    @property
    def blue(self):
        "Return the blue value as a :class:`Blue` instance"
        return Blue(self[2])


class HLS(tuple):
    "Named tuple representing hue, lightness, and saturation."
    # NOTE: This source mostly generated by namedtuple(..., verbose=True)

    __slots__ = ()

    _fields = ('h', 'l', 's')

    def __new__(cls, h, l, s):
        return tuple.__new__(cls, (h, l, s))

    def _replace(self, **kw):
        "Return a new HLS object replacing specified fields with new values"
        # pylint: disable=bad-builtin
        result = tuple.__new__(HLS, map(kw.pop, 'hls', self))
        if kw:
            raise ValueError('Got unexpected field names: %r' % list(kw))
        return result

    def __repr__(self):
        "Return a nicely formatted representation string"
        return self.__class__.__name__ + '(h=%r, l=%r, s=%r)' % self

    def _asdict(self):
        "Return a new OrderedDict which maps field names to their values."
        return OrderedDict(zip(self._fields, self))

    def __getnewargs__(self):
        "Return self as a plain tuple.  Used by copy and pickle."
        return tuple(self)

    @property
    def h(self):
        "Return the hue value as a :class:`Hue` instance"
        # pylint: disable=invalid-name
        return Hue(self[0])

    @property
    def hue(self):
        "Return the hue value as a :class:`Hue` instance"
        return Hue(self[0])

    @property
    def l(self):
        "Return the lightness value as a :class:`Lightness` instance"
        # pylint: disable=invalid-name
        return Lightness(self[1])

    @property
    def lightness(self):
        "Return the lightness value as a :class:`Lightness` instance"
        return Lightness(self[1])

    @property
    def s(self):
        "Return the saturation value as a :class:`Saturation` instance"
        # pylint: disable=invalid-name
        return Saturation(self[2])

    @property
    def saturation(self):
        "Return the saturation value as a :class:`Saturation` instance"
        return Saturation(self[2])


class HSV(tuple):
    'Named tuple representing hue, saturation, and value ("brightness").'

    __slots__ = ()

    _fields = ('h', 's', 'v')

    def __new__(cls, h, s, v):
        return tuple.__new__(cls, (h, s, v))

    def _replace(self, **kw):
        "Return a new HSV object replacing specified fields with new values"
        # pylint: disable=bad-builtin
        result = tuple.__new__(HSV, map(kw.pop, 'hsv', self))
        if kw:
            raise ValueError('Got unexpected field names: %r' % list(kw))
        return result

    def __repr__(self):
        "Return a nicely formatted representation string"
        return self.__class__.__name__ + '(h=%r, s=%r, v=%r)' % self

    def _asdict(self):
        "Return a new OrderedDict which maps field names to their values."
        return OrderedDict(zip(self._fields, self))

    def __getnewargs__(self):
        "Return self as a plain tuple.  Used by copy and pickle."
        return tuple(self)

    @property
    def h(self):
        "Return the hue value as a :class:`Hue` instance"
        # pylint: disable=invalid-name
        return Hue(self[0])

    @property
    def hue(self):
        "Return the hue value as a :class:`Hue` instance"
        return Hue(self[0])

    @property
    def s(self):
        "Return the saturation value as a :class:`Saturation` instance"
        # pylint: disable=invalid-name
        return Saturation(self[1])

    @property
    def saturation(self):
        "Return the saturation value as a :class:`Saturation` instance"
        return Saturation(self[1])

    @property
    def v(self):
        "Return the brightness value"
        return self[2]

    @property
    def value(self):
        "Return the brightness value"
        return self[2]


class YUV(tuple):
    "Named tuple representing luma and two chroma offsets"

    __slots__ = ()

    _fields = ('y', 'u', 'v')

    def __new__(cls, y, u, v):
        return tuple.__new__(cls, (y, u, v))

    def _replace(self, **kw):
        "Return a new YUV object replacing specified fields with new values"
        # pylint: disable=bad-builtin
        result = tuple.__new__(YUV, map(kw.pop, 'yuv', self))
        if kw:
            raise ValueError('Got unexpected field names: %r' % list(kw))
        return result

    def __repr__(self):
        "Return a nicely formatted representation string"
        return self.__class__.__name__ + '(y=%r, u=%r, v=%r)' % self

    def _asdict(self):
        "Return a new OrderedDict which maps field names to their values."
        return OrderedDict(zip(self._fields, self))

    def __getnewargs__(self):
        "Return self as a plain tuple.  Used by copy and pickle."
        return tuple(self)

    @property
    def y(self):
        "Return the luma value as a :class:`Luma` instance"
        # pylint: disable=invalid-name
        return Luma(self[0])

    @property
    def luma(self):
        "Return the luma value as a :class:`Luma` instance"
        return Luma(self[0])

    @property
    def u(self):
        "Return the first chroma offset"
        # pylint: disable=invalid-name
        return self[1]

    @property
    def v(self):
        "Return the second chroma offset"
        # pylint: disable=invalid-name
        return self[2]


class CMY(namedtuple('CMY', ('c', 'm', 'y'))):
    "Named tuple representing cyan, magenta, and yellow."

    @property
    def cyan(self):
        # pylint: disable=missing-docstring
        return self.c

    @property
    def magenta(self):
        # pylint: disable=missing-docstring
        return self.m

    @property
    def yellow(self):
        # pylint: disable=missing-docstring
        return self.y


class CMYK(namedtuple('CMYK', ('c', 'm', 'y', 'k'))):
    "Named tuple representing cyan, magenta, yellow, and black."

    @property
    def cyan(self):
        # pylint: disable=missing-docstring
        return self.c

    @property
    def magenta(self):
        # pylint: disable=missing-docstring
        return self.m

    @property
    def yellow(self):
        # pylint: disable=missing-docstring
        return self.y

    @property
    def black(self):
        # pylint: disable=missing-docstring
        return self.k


YIQ = namedtuple('YIQ', ('y', 'i', 'q'))
XYZ = namedtuple('XYZ', ('x', 'y', 'z'))
Luv = namedtuple('Luv', ('l', 'u', 'v'))
Lab = namedtuple('Lab', ('l', 'a', 'b'))
