/*
 * Copyright 2022 Rive
 */

#include "pls_paint.hpp"

#include "rive/pls/pls_image.hpp"

namespace rive::pls
{
PLSPaint::PLSPaint() {}

PLSPaint::~PLSPaint() {}

// Ensure the given gradient stops are in a format expected by PLS.
static bool validate_gradient_stops(const ColorInt colors[], // [count]
                                    const float stops[],     // [count]
                                    size_t count)
{
    // Stops cannot be empty.
    if (count == 0)
    {
        return false;
    }
    for (size_t i = 0; i < count; ++i)
    {
        // Stops must be finite, real numbers in the range [0, 1].
        if (!(0 <= stops[i] && stops[i] <= 1))
        {
            return false;
        }
    }
    for (size_t i = 1; i < count; ++i)
    {
        // Stops must be ordered.
        if (!(stops[i - 1] <= stops[i]))
        {
            return false;
        }
    }
    return true;
}

rcp<PLSGradient> PLSGradient::MakeLinear(float sx,
                                         float sy,
                                         float ex,
                                         float ey,
                                         const ColorInt colors[], // [count]
                                         const float stops[],     // [count]
                                         size_t count)
{
    if (!validate_gradient_stops(colors, stops, count))
    {
        return nullptr;
    }

    float2 start = {sx, sy};
    float2 end = {ex, ey};
    PLSGradDataArray<ColorInt> newColors(colors, count);
    PLSGradDataArray<float> newStops(stops, count);

    // If the stops don't begin and end on 0 and 1, transform the gradient so they do. This allows
    // us to take full advantage of the gradient's range of pixels in the texture.
    float firstStop = stops[0];
    float lastStop = stops[count - 1];
    if ((firstStop != 0 || lastStop != 1) && lastStop - firstStop > math::EPSILON)
    {
        // Tighten the endpoints to align with the mininum and maximum gradient stops.
        float4 newEndpoints = simd::precise_mix(start.xyxy,
                                                end.xyxy,
                                                float4{firstStop, firstStop, lastStop, lastStop});
        start = newEndpoints.xy;
        end = newEndpoints.zw;
        newStops[0] = 0;
        newStops[count - 1] = 1;
        if (count > 2)
        {
            // Transform the stops into the range defined by the new endpoints.
            float m = 1.f / (lastStop - firstStop);
            float a = -firstStop * m;
            for (size_t i = 1; i < count - 1; ++i)
            {
                newStops[i] = stops[i] * m + a;
            }

            // Clamp the interior stops so they remain monotonically increasing. newStops[0] and
            // newStops[count - 1] are already 0 and 1, so this also ensures they stay within 0..1.
            for (size_t i = 1; i < count - 1; ++i)
            {
                newStops[i] = fmaxf(newStops[i - 1], newStops[i]);
            }
            for (size_t i = count - 2; i != 0; --i)
            {
                newStops[i] = fminf(newStops[i], newStops[i + 1]);
            }
        }
        assert(validate_gradient_stops(newColors.get(), newStops.get(), count));
    }

    float2 v = end - start;
    v *= 1.f / simd::dot(v, v); // dot(v, end - start) == 1
    return rcp(new PLSGradient(PaintType::linearGradient,
                               std::move(newColors),
                               std::move(newStops),
                               count,
                               v.x,
                               v.y,
                               -simd::dot(v, start)));
}

rcp<PLSGradient> PLSGradient::MakeRadial(float cx,
                                         float cy,
                                         float radius,
                                         const ColorInt colors[], // [count]
                                         const float stops[],     // [count]
                                         size_t count)
{
    if (!validate_gradient_stops(colors, stops, count))
    {
        return nullptr;
    }

    PLSGradDataArray<ColorInt> newColors(colors, count);
    PLSGradDataArray<float> newStops(stops, count);

    // If the stops don't end on 1, scale the gradient so they do. This allows us to take better
    // advantage of the gradient's full range of pixels in the texture.
    //
    // TODO: If we want to take full advantage of the gradient texture pixels, we could add an inner
    // radius that specifies where t=0 begins (instead of assuming it begins at the center).
    float lastStop = stops[count - 1];
    if (lastStop != 1 && lastStop > math::EPSILON)
    {
        // Update the gradient to finish on 1.
        newStops[count - 1] = 1;

        // Scale the radius to align with the final stop.
        radius *= lastStop;

        // Scale the stops into the range defined by the new radius.
        float inverseLastStop = 1.f / lastStop;
        for (size_t i = 0; i < count - 1; ++i)
        {
            newStops[i] = stops[i] * inverseLastStop;
        }

        if (count > 1)
        {
            // Clamp the stops so they remain monotonically increasing. newStops[count - 1] is
            // already 1, so this also ensures they stay within 0..1.
            newStops[0] = fmaxf(0, newStops[0]);
            for (size_t i = 1; i < count - 1; ++i)
            {
                newStops[i] = fmaxf(newStops[i - 1], newStops[i]);
            }
            for (size_t i = count - 2; i != -1; --i)
            {
                newStops[i] = fminf(newStops[i], newStops[i + 1]);
            }
        }

        assert(validate_gradient_stops(newColors.get(), newStops.get(), count));
    }

    return rcp(new PLSGradient(PaintType::radialGradient,
                               std::move(newColors),
                               std::move(newStops),
                               count,
                               cx,
                               cy,
                               radius));
}

bool PLSGradient::isOpaque() const
{
    if (m_isOpaque == pls::TriState::unknown)
    {
        ColorInt allColors = ~0;
        for (int i = 0; i < m_count; ++i)
        {
            allColors &= m_colors[i];
        }
        m_isOpaque = colorAlpha(allColors) == 0xff ? pls::TriState::yes : pls::TriState::no;
    }
    return m_isOpaque == pls::TriState::yes;
}

void PLSPaint::color(ColorInt color)
{
    m_paintType = PaintType::solidColor;
    m_simpleValue.color = color;
    m_gradient.reset();
    m_imageTexture.reset();
}

void PLSPaint::shader(rcp<RenderShader> shader)
{
    m_gradient = static_rcp_cast<PLSGradient>(std::move(shader));
    m_paintType = m_gradient ? m_gradient->paintType() : PaintType::solidColor;
    // m_simpleValue.colorRampLocation is unused at this level. A new location for a this gradient's
    // color ramp will decided by the render context every frame.
    m_simpleValue.color = 0xff000000;
    m_imageTexture.reset();
}

void PLSPaint::image(rcp<const PLSTexture> imageTexture, float opacity)
{
    m_paintType = PaintType::image;
    m_simpleValue.imageOpacity = opacity;
    m_gradient.reset();
    m_imageTexture = std::move(imageTexture);
}

void PLSPaint::clipUpdate(uint32_t outerClipID)
{
    m_paintType = PaintType::clipUpdate;
    m_simpleValue.outerClipID = outerClipID;
    m_gradient.reset();
    m_imageTexture.reset();
}

bool PLSPaint::getIsOpaque() const
{
    switch (m_paintType)
    {
        case pls::PaintType::solidColor:
            return colorAlpha(m_simpleValue.color) == 0xff;
        case pls::PaintType::linearGradient:
        case pls::PaintType::radialGradient:
            return m_gradient->isOpaque();
        case pls::PaintType::image:
        case pls::PaintType::clipUpdate:
            return false;
    }
    RIVE_UNREACHABLE();
}
} // namespace rive::pls
