/*
 * Copyright 2022 Rive
 */

#pragma once

#include "rive/renderer/gpu.hpp"
#include "rive/renderer.hpp"
#include <array>

namespace rive::gpu
{

// Copies an array of colors or stops for a gradient.
// Stores the data locally if there are 4 values or fewer.
// Spills onto the heap if there are >4 values.
template <typename T> class GradDataArray
{
public:
    static_assert(std::is_trivial_v<T> && std::is_standard_layout<T>());

    GradDataArray(const T data[], size_t count)
    {
        m_data =
            count <= m_localData.size() ? m_localData.data() : new T[count];
        memcpy(m_data, data, count * sizeof(T));
    }

    // Allocate without initializing (caller must fill in data).
    explicit GradDataArray(size_t count)
    {
        m_data =
            count <= m_localData.size() ? m_localData.data() : new T[count];
    }

    GradDataArray(GradDataArray&& other)
    {
        if (other.m_data == other.m_localData.data())
        {
            m_localData = other.m_localData;
            m_data = m_localData.data();
        }
        else
        {
            m_data = other.m_data;
            other.m_data =
                other.m_localData.data(); // Don't delete[] other.m_data.
        }
    }

    ~GradDataArray()
    {
        if (m_data != m_localData.data())
        {
            delete[] m_data;
        }
    }

    const T* get() const { return m_data; }
    const T operator[](size_t i) const { return m_data[i]; }
    T& operator[](size_t i) { return m_data[i]; }

private:
    std::array<T, 4> m_localData;
    T* m_data;
};

// RenderShader implementation for Rive's pixel local storage renderer.
class Gradient : public LITE_RTTI_OVERRIDE(RenderShader, Gradient)
{
public:
    static rcp<Gradient> MakeLinear(float sx,
                                    float sy,
                                    float ex,
                                    float ey,
                                    const ColorInt colors[], // [count]
                                    const float stops[],     // [count]
                                    size_t count);

    static rcp<Gradient> MakeRadial(float cx,
                                    float cy,
                                    float radius,
                                    const ColorInt colors[], // [count]
                                    const float stops[],     // [count]
                                    size_t count);

    PaintType paintType() const { return m_paintType; }
    const float* coeffs() const { return m_coeffs.data(); }
    const ColorInt* colors() const { return m_colors.get(); }
    const float* stops() const { return m_stops.get(); }
    size_t count() const { return m_count; }
    bool isOpaque() const;

    // Get or create a modulated variant of this gradient.
    // Caches the last-used modulated gradient for efficient reuse when the same
    // modulation is requested multiple times (e.g., multiple draws in one
    // frame).
    rcp<Gradient> getModulated(float opacity,
                               ColorInt color = 0xFFFFFFFF) const;

private:
    Gradient(PaintType paintType,
             GradDataArray<ColorInt>&& colors, // [count]
             GradDataArray<float>&& stops,     // [count]
             size_t count,
             float coeffX,
             float coeffY,
             float coeffZ) :
        m_paintType(paintType),
        m_colors(std::move(colors)),
        m_stops(std::move(stops)),
        m_count(count),
        m_coeffs{coeffX, coeffY, coeffZ}
    {
        assert(paintType == gpu::PaintType::linearGradient ||
               paintType == gpu::PaintType::radialGradient);
    }

    PaintType m_paintType; // Specifically, linearGradient or radialGradient.
    GradDataArray<ColorInt> m_colors;
    GradDataArray<float> m_stops;
    size_t m_count;
    std::array<float, 3> m_coeffs;
    mutable gpu::TriState m_isOpaque = gpu::TriState::unknown;

    // Single-entry cache for last-used modulated gradient
    mutable rcp<Gradient> m_lastModulatedGradient;
    mutable float m_lastModulatedOpacity =
        -1.0f; // -1 as sentinel (valid range is 0..1)
    mutable ColorInt m_lastModulatedColor = 0xFFFFFFFF;
};

} // namespace rive::gpu
