/*
 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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.
 */

#include "config.h"
#include "ColorConversion.h"

#include "Color.h"
#include "ColorSpace.h"
#include "DestinationColorSpace.h"
#include <wtf/MathExtras.h>

namespace WebCore {

// MARK: Lab-Like to LCH-Like conversion utilities.

template<typename LCHLike, typename LabLike>
LCHLike convertToPolarForm(const LabLike& color)
{
    // https://drafts.csswg.org/css-color/#lab-to-lch
    float hue = rad2deg(atan2(color.b, color.a));

    return {
        color.lightness,
        std::hypot(color.a, color.b),
        hue >= 0 ? hue : hue + 360,
        color.alpha
    };
}

template<typename LabLike, typename LCHLike>
LabLike convertToRectangularForm(const LCHLike& color)
{
    // https://drafts.csswg.org/css-color/#lch-to-lab
    float hueAngleRadians = deg2rad(color.hue);

    return {
        color.lightness,
        color.chroma * std::cos(hueAngleRadians),
        color.chroma * std::sin(hueAngleRadians),
        color.alpha
    };
}

// MARK: HSL conversions.

struct HSLHueCalculationResult {
    float hue;
    float min;
    float max;
    float chroma;
};

static HSLHueCalculationResult calculateHSLHue(const SRGBA<float>& color)
{
    auto [r, g, b, alpha] = color;
    auto [min, max] = std::minmax({ r, g, b });
    float chroma = max - min;

    float hue;
    if (!chroma)
        hue = 0;
    else if (max == r)
        hue = (60.0f * ((g - b) / chroma)) + 360.0f;
    else if (max == g)
        hue = (60.0f * ((b - r) / chroma)) + 120.0f;
    else
        hue = (60.0f * ((r - g) / chroma)) + 240.0f;

    if (hue >= 360.0f)
        hue -= 360.0f;

    return { hue, min, max, chroma };
}

HSLA<float> ColorConversion<HSLA<float>, SRGBA<float>>::convert(const SRGBA<float>& color)
{
    // https://drafts.csswg.org/css-color-4/#hsl-to-rgb
    auto [r, g, b, alpha] = color;
    auto [hue, min, max, chroma] = calculateHSLHue(color);

    float lightness = (0.5f * (max + min)) * 100.0f;
    float saturation;
    if (!chroma)
        saturation = 0;
    else if (lightness <= 50.0f)
        saturation = (chroma / (max + min)) * 100.0f;
    else
        saturation = (chroma / (2.0f - (max + min))) * 100.0f;

    return { hue, saturation, lightness, alpha };
}

SRGBA<float> ColorConversion<SRGBA<float>, HSLA<float>>::convert(const HSLA<float>& color)
{
    // https://drafts.csswg.org/css-color-4/#hsl-to-rgb
    auto [hue, saturation, lightness, alpha] = color;

    if (!saturation) {
        auto grey = lightness / 100.0f;
        return { grey, grey, grey, alpha };
    }

    // hueToRGB() wants hue in the 0-6 range.
    auto normalizedHue = (hue / 360.0f) * 6.0f;
    auto normalizedLightness = lightness / 100.0f;
    auto normalizedSaturation = saturation / 100.0f;

    auto hueForRed = normalizedHue + 2.0f;
    auto hueForGreen = normalizedHue;
    auto hueForBlue = normalizedHue - 2.0f;
    if (hueForRed > 6.0f)
        hueForRed -= 6.0f;
    else if (hueForBlue < 0.0f)
        hueForBlue += 6.0f;

    float temp2 = normalizedLightness <= 0.5f ? normalizedLightness * (1.0f + normalizedSaturation) : normalizedLightness + normalizedSaturation - normalizedLightness * normalizedSaturation;
    float temp1 = 2.0f * normalizedLightness - temp2;
    
    // Hue is in the range 0-6, other args in 0-1.
    auto hueToRGB = [](float temp1, float temp2, float hue) {
        if (hue < 1.0f)
            return temp1 + (temp2 - temp1) * hue;
        if (hue < 3.0f)
            return temp2;
        if (hue < 4.0f)
            return temp1 + (temp2 - temp1) * (4.0f - hue);
        return temp1;
    };

    return {
        hueToRGB(temp1, temp2, hueForRed),
        hueToRGB(temp1, temp2, hueForGreen),
        hueToRGB(temp1, temp2, hueForBlue),
        alpha
    };
}

// MARK: HWB conversions.

HWBA<float> ColorConversion<HWBA<float>, SRGBA<float>>::convert(const SRGBA<float>& color)
{
    // https://drafts.csswg.org/css-color-4/#rgb-to-hwb
    auto [hue, min, max, chroma] = calculateHSLHue(color);
    auto whiteness = min * 100.0f;
    auto blackness = (1.0f - max) * 100.0f;
    
    return { hue, whiteness, blackness, color.alpha };
}

SRGBA<float> ColorConversion<SRGBA<float>, HWBA<float>>::convert(const HWBA<float>& color)
{
    // https://drafts.csswg.org/css-color-4/#hwb-to-rgb
    auto [hue, whiteness, blackness, alpha] = color;

    if (whiteness + blackness == 100.0f) {
        auto grey = whiteness / 100.0f;
        return { grey, grey, grey, alpha };
    }

    // hueToRGB() wants hue in the 0-6 range.
    auto normalizedHue = (hue / 360.0f) * 6.0f;

    auto hueForRed = normalizedHue + 2.0f;
    auto hueForGreen = normalizedHue;
    auto hueForBlue = normalizedHue - 2.0f;
    if (hueForRed > 6.0f)
        hueForRed -= 6.0f;
    else if (hueForBlue < 0.0f)
        hueForBlue += 6.0f;

    auto normalizedWhiteness = whiteness / 100.0f;
    auto normalizedBlackness = blackness / 100.0f;

    // This is the hueToRGB function in convertColor<SRGBA<float>>(const HSLA&) with temp1 == 0
    // and temp2 == 1 strength reduced through it.
    auto hueToRGB = [](float hue) {
        if (hue < 1.0f)
            return hue;
        if (hue < 3.0f)
            return 1.0f;
        if (hue < 4.0f)
            return 4.0f - hue;
        return 0.0f;
    };

    auto applyWhitenessBlackness = [](float component, auto whiteness, auto blackness) {
        return (component * (1.0f - whiteness - blackness)) + whiteness;
    };

    return {
        applyWhitenessBlackness(hueToRGB(hueForRed), normalizedWhiteness, normalizedBlackness),
        applyWhitenessBlackness(hueToRGB(hueForGreen), normalizedWhiteness, normalizedBlackness),
        applyWhitenessBlackness(hueToRGB(hueForBlue), normalizedWhiteness, normalizedBlackness),
        alpha
    };
}

// MARK: Lab conversions.

static constexpr float LABe = 216.0f / 24389.0f;
static constexpr float LABk = 24389.0f / 27.0f;
static constexpr float D50WhiteValues[] = { 0.96422f, 1.0f, 0.82521f };

XYZA<float, WhitePoint::D50> ColorConversion<XYZA<float, WhitePoint::D50>, Lab<float>>::convert(const Lab<float>& color)
{
    float f1 = (color.lightness + 16.0f) / 116.0f;
    float f0 = f1 + (color.a / 500.0f);
    float f2 = f1 - (color.b / 200.0f);

    auto computeXAndZ = [](float t) {
        float tCubed = t * t * t;
        if (tCubed > LABe)
            return tCubed;

        return (116.0f * t - 16.0f) / LABk;
    };

    auto computeY = [](float t) {
        if (t > (LABk * LABe)) {
            float value = (t + 16.0) / 116.0;
            return value * value * value;
        }

        return t / LABk;
    };

    float x = D50WhiteValues[0] * computeXAndZ(f0);
    float y = D50WhiteValues[1] * computeY(color.lightness);
    float z = D50WhiteValues[2] * computeXAndZ(f2);

    return { x, y, z, color.alpha };
}

Lab<float> ColorConversion<Lab<float>, XYZA<float, WhitePoint::D50>>::convert(const XYZA<float, WhitePoint::D50>& color)
{
    float x = color.x / D50WhiteValues[0];
    float y = color.y / D50WhiteValues[1];
    float z = color.z / D50WhiteValues[2];

    auto fTransform = [](float value) {
        return value > LABe ? std::cbrt(value) : (LABk * value + 16.0f) / 116.0f;
    };

    float f0 = fTransform(x);
    float f1 = fTransform(y);
    float f2 = fTransform(z);

    float lightness = (116.0f * f1) - 16.0f;
    float a = 500.0f * (f0 - f1);
    float b = 200.0f * (f1 - f2);

    return { lightness, a, b, color.alpha };
}

// MARK: LCH conversions.

LCHA<float> ColorConversion<LCHA<float>, Lab<float>>::convert(const Lab<float>& color)
{
    return convertToPolarForm<LCHA<float>>(color);
}

Lab<float> ColorConversion<Lab<float>, LCHA<float>>::convert(const LCHA<float>& color)
{
    return convertToRectangularForm<Lab<float>>(color);
}

// MARK: OKLab conversions.

XYZA<float, WhitePoint::D65> ColorConversion<XYZA<float, WhitePoint::D65>, OKLab<float>>::convert(const OKLab<float>& color)
{
    // FIXME: This could be optimized for when we are not explicitly converting to XYZ-D65 by pre-multiplying the 'LMSToXYZD65'
    // matrix with any subsequent matrices in the conversion. This would mean teaching the main conversion about this matrix
    // and adding new logic for this transform.

    // https://bottosson.github.io/posts/oklab/ with XYZ <-> LMS matrices recalculated for consistent reference white in https://github.com/w3c/csswg-drafts/issues/6642#issuecomment-943521484

    static constexpr ColorMatrix<3, 3> LinearLMSToXYZD65 {
        1.2268798733741557f,  -0.5578149965554813f,  0.28139105017721583f,
       -0.04057576262431372f,  1.1122868293970594f, -0.07171106666151701f,
       -0.07637294974672142f, -0.4214933239627914f,  1.5869240244272418f
    };

    static constexpr ColorMatrix<3, 3> OKLabToNonLinearLMS {
        0.99999999845051981432f,  0.39633779217376785678f,   0.21580375806075880339f,
        1.0000000088817607767f,  -0.1055613423236563494f,   -0.063854174771705903402f,
        1.0000000546724109177f,  -0.089484182094965759684f, -1.2914855378640917399f
    };

    // 1. Transform from precentage lightness to unit lightness.
    auto components = asColorComponents(color).subset<0, 3>();
    components[0] = components[0] / 100.0f;

    // 2. Transform from Lab-coordinates into non-linear LMS "approximate cone responses".
    auto nonLinearLMS = OKLabToNonLinearLMS.transformedColorComponents(components);

    // 3. Apply linearity.
    auto linearLMS = nonLinearLMS.map([] (float v) { return v * v * v; });

    // 4. Convert to XYZ.
    auto [x, y, z] = LinearLMSToXYZD65.transformedColorComponents(linearLMS);

    return { x, y, z, color.alpha };
}

OKLab<float> ColorConversion<OKLab<float>, XYZA<float, WhitePoint::D65>>::convert(const XYZA<float, WhitePoint::D65>& color)
{
    // FIXME: This could be optimized for when we are not explicitly converting from XYZ-D65 by pre-multiplying the 'XYZD65ToLMS'
    // matrix with any previous matrices in the conversion. This would mean teaching the main conversion about this matrix
    // and adding new logic for this transform.

    // https://bottosson.github.io/posts/oklab/ with XYZ <-> LMS matrices recalculated for consistent reference white in https://github.com/w3c/csswg-drafts/issues/6642#issuecomment-943521484

    static constexpr ColorMatrix<3, 3> XYZD65ToLinearLMS {
        0.8190224432164319f,   0.3619062562801221f, -0.12887378261216414f,
        0.0329836671980271f,   0.9292868468965546f,  0.03614466816999844f,
        0.048177199566046255f, 0.26423952494422764f, 0.6335478258136937f
    };

    static constexpr ColorMatrix<3, 3> NonLinearLMSToOKLab {
        0.2104542553f,  0.7936177850f, -0.0040720468f,
        1.9779984951f, -2.4285922050f,  0.4505937099f,
        0.0259040371f,  0.7827717662f, -0.8086757660f
    };

    // 1. Convert XYZ into LMS "approximate cone responses".
    auto linearLMS = XYZD65ToLinearLMS.transformedColorComponents(asColorComponents(color).subset<0, 3>());

    // 2. Apply non-linearity.
    auto nonLinearLMS = linearLMS.map([] (float v) { return std::cbrt(v); });

    // 3. Transform into Lab-coordinates.
    auto [lightness, a, b] = NonLinearLMSToOKLab.transformedColorComponents(nonLinearLMS);

    // 4. Transform lightness from unit lightness to percentage lightness.
    return { lightness * 100.0f, a, b, color.alpha };
}

// MARK: OKLCH conversions.

OKLCHA<float> ColorConversion<OKLCHA<float>, OKLab<float>>::convert(const OKLab<float>& color)
{
    return convertToPolarForm<OKLCHA<float>>(color);
}

OKLab<float> ColorConversion<OKLab<float>, OKLCHA<float>>::convert(const OKLCHA<float>& color)
{
    return convertToRectangularForm<OKLab<float>>(color);
}

// MARK: Conversion functions for raw color components with associated color spaces.

ColorComponents<float, 4> convertColorComponents(ColorSpace inputColorSpace, ColorComponents<float, 4> inputColorComponents, ColorSpace outputColorSpace)
{
    return callWithColorType(inputColorComponents, inputColorSpace, [outputColorSpace] (const auto& inputColor) {
        switch (outputColorSpace) {
        case ColorSpace::A98RGB:
            return asColorComponents(convertColor<A98RGB<float>>(inputColor));
        case ColorSpace::DisplayP3:
            return asColorComponents(convertColor<DisplayP3<float>>(inputColor));
        case ColorSpace::LCH:
            return asColorComponents(convertColor<LCHA<float>>(inputColor));
        case ColorSpace::Lab:
            return asColorComponents(convertColor<Lab<float>>(inputColor));
        case ColorSpace::LinearSRGB:
            return asColorComponents(convertColor<LinearSRGBA<float>>(inputColor));
        case ColorSpace::OKLCH:
            return asColorComponents(convertColor<OKLCHA<float>>(inputColor));
        case ColorSpace::OKLab:
            return asColorComponents(convertColor<OKLab<float>>(inputColor));
        case ColorSpace::ProPhotoRGB:
            return asColorComponents(convertColor<ProPhotoRGB<float>>(inputColor));
        case ColorSpace::Rec2020:
            return asColorComponents(convertColor<Rec2020<float>>(inputColor));
        case ColorSpace::SRGB:
            return asColorComponents(convertColor<SRGBA<float>>(inputColor));
        case ColorSpace::XYZ_D50:
            return asColorComponents(convertColor<XYZA<float, WhitePoint::D50>>(inputColor));
        case ColorSpace::XYZ_D65:
            return asColorComponents(convertColor<XYZA<float, WhitePoint::D65>>(inputColor));
        }

        ASSERT_NOT_REACHED();
        return asColorComponents(convertColor<SRGBA<float>>(inputColor));
    });
}

ColorComponents<float, 4> convertColorComponents(ColorSpace inputColorSpace, ColorComponents<float, 4> inputColorComponents, const DestinationColorSpace& outputColorSpace)
{
#if USE(CG)
    return platformConvertColorComponents(inputColorSpace, inputColorComponents, outputColorSpace);
#else
    return callWithColorType(inputColorComponents, inputColorSpace, [outputColorSpace] (const auto& inputColor) {
        switch (outputColorSpace.platformColorSpace()) {
        case PlatformColorSpace::Name::SRGB:
            return asColorComponents(convertColor<SRGBA<float>>(inputColor));
#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
        case PlatformColorSpace::Name::LinearSRGB:
            return asColorComponents(convertColor<LinearSRGBA<float>>(inputColor));
#endif
#if ENABLE(DESTINATION_COLOR_SPACE_DISPLAY_P3)
        case PlatformColorSpace::Name::DisplayP3:
            return asColorComponents(convertColor<DisplayP3<float>>(inputColor));
#endif
        }

        ASSERT_NOT_REACHED();
        return asColorComponents(convertColor<SRGBA<float>>(inputColor));
    });
#endif
}

} // namespace WebCore
