#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Functions for converting and comparing colors."""

import colorsys
import operator


def _hls_hsv_to_rgb(converter_func, value1, value2, value3):
    """Convert HLS or HSV to RGB via a converter function."""
    return tuple(
        int(c * 255.) for c in converter_func(
            value1 / 360.,
            value2 / 100.,
            value3 / 100.,
        )
    )


def hls_to_rgb(hue, lightness, saturation):
    """Convert HLS (hue, lightness, saturation) values to RGB."""
    if hue < 0. or hue > 360.:
        raise ValueError('Hue must be in range 0.0-360.0 inclusive')

    if lightness < 0. or lightness > 100.:
        raise ValueError('Lightness must be in range 0.0-100.0 inclusive')

    if saturation < 0. or saturation > 100.:
        raise ValueError('Saturation must be in range 0.0-100.0 inclusive')

    return _hls_hsv_to_rgb(colorsys.hls_to_rgb, hue, lightness, saturation)


def hsv_to_rgb(hue, saturation, value):
    """Convert HSV (hue, saturation, value) values to RGB."""
    if hue < 0. or hue > 360.:
        raise ValueError('Hue must be in range 0.0-360.0 inclusive')

    if saturation < 0. or saturation > 100.:
        raise ValueError('Saturation must be in range 0.0-100.0 inclusive')

    if value < 0. or value > 100.:
        raise ValueError('Value must be in range 0.0-100.0 inclusive')

    return _hls_hsv_to_rgb(colorsys.hsv_to_rgb, hue, saturation, value)


def color_difference(rgb1, rgb2):
    """Return the sums of component differences between two colors."""
    return sum(abs(i - j) for i, j in zip(rgb1, rgb2))


def closest_color(rgb, clut):
    """Return the CLUT index of the closest RGB color to a given RGB tuple."""
    # Generate a list of tuples of CLUT indices and the color difference value
    indexed_diffs = ((idx, color_difference(rgb, clut[idx])) for idx in clut)

    return min(indexed_diffs, key=operator.itemgetter(1))[0]
