""" This module is generated by transpiling Haxe into Python and cleaning
the resulting code by hand, e.g. removing unused Haxe classes. To try it
yourself, clone https://github.com/hsluv/hsluv and run:

    haxe -cp haxe/src hsluv.Hsluv -python hsluv.py
"""

from functools import wraps as _wraps, partial as _partial  # unexport, see #17
import math as _math  # unexport, see #17


__version__ = '5.0.2'

_m = [[3.240969941904521, -1.537383177570093, -0.498610760293],
      [-0.96924363628087, 1.87596750150772, 0.041555057407175],
      [0.055630079696993, -0.20397695888897, 1.056971514242878]]
_min_v = [[0.41239079926595, 0.35758433938387, 0.18048078840183],
          [0.21263900587151, 0.71516867876775, 0.072192315360733],
          [0.019330818715591, 0.11919477979462, 0.95053215224966]]
_ref_y = 1.0
_ref_u = 0.19783000664283
_ref_v = 0.46831999493879
_kappa = 903.2962962
_epsilon = 0.0088564516


def _normalize_output(conversion):
    # as in snapshot rev 4, the tolerance should be 1e-11
    normalize = _partial(round, ndigits=11-1)

    @_wraps(conversion)
    def normalized(*args, **kwargs):
        color = conversion(*args, **kwargs)
        return tuple(normalize(c) for c in color)
    return normalized


def _distance_line_from_origin(line):
    v = line['slope'] ** 2 + 1
    return abs(line['intercept']) / _math.sqrt(v)


def _length_of_ray_until_intersect(theta, line):
    return line['intercept']\
         / (_math.sin(theta) - line['slope'] * _math.cos(theta))


def _get_bounds(l):
    result = []
    sub1 = ((l + 16) ** 3) / 1560896
    if sub1 > _epsilon:
        sub2 = sub1
    else:
        sub2 = l / _kappa
    _g = 0
    while _g < 3:
        c = _g
        _g += 1
        m1 = _m[c][0]
        m2 = _m[c][1]
        m3 = _m[c][2]
        _g1 = 0
        while _g1 < 2:
            t = _g1
            _g1 += 1
            top1 = (284517 * m1 - 94839 * m3) * sub2
            top2 = (838422 * m3 + 769860 * m2 + 731718 * m1)\
                * l * sub2 - (769860 * t) * l
            bottom = (632260 * m3 - 126452 * m2) * sub2 + 126452 * t
            result.append({'slope': top1 / bottom, 'intercept': top2 / bottom})
    return result


def _max_safe_chroma_for_l(l):
    return min(_distance_line_from_origin(bound)
            for bound in _get_bounds(l))


def _max_chroma_for_lh(l, h):
    hrad = _math.radians(h)
    lengths = [_length_of_ray_until_intersect(hrad, bound) for bound in _get_bounds(l)]
    return min(length for length in lengths if length >= 0)


def _dot_product(a, b):
    return sum(i * j for i, j in zip(a, b))


def _from_linear(c):
    if c <= 0.0031308:
        return 12.92 * c

    return 1.055 * _math.pow(c, 5 / 12) - 0.055


def _to_linear(c):
    if c > 0.04045:
        return _math.pow((c + 0.055) / 1.055, 2.4)

    return c / 12.92


def _y_to_l(y):