#include "rive/shapes/paint/linear_gradient.hpp"
#include "rive/math/vec2d.hpp"
#include "rive/artboard.hpp"
#include "rive/factory.hpp"
#include "rive/node.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/paint/color.hpp"
#include "rive/shapes/paint/gradient_stop.hpp"
#include "rive/shapes/shape_paint_container.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include <algorithm>

using namespace rive;

StatusCode LinearGradient::onAddedDirty(CoreContext* context)
{
    StatusCode code = Super::onAddedDirty(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }

    if (!initPaintMutator(this))
    {
        return StatusCode::MissingObject;
    }
    return StatusCode::Ok;
}

void LinearGradient::buildDependencies()
{
    auto p = parent();
    if (p != nullptr && p->parent() != nullptr)
    {
        auto parentsParent = p->parent();
        // Parent's parent must be a shape paint container.
        assert(ShapePaintContainer::from(parentsParent) != nullptr);

        // TODO: see if artboard should inherit from some TransformComponent
        // that can return a world transform. We store the container just for
        // doing the transform to world in update. If it's the artboard, then
        // we're already in world so no need to transform.
        m_ShapePaintContainer = parentsParent->is<Node>() ? parentsParent->as<Node>() : nullptr;
        parentsParent->addDependent(this);
    }
}

void LinearGradient::addStop(GradientStop* stop) { m_Stops.push_back(stop); }

static bool stopsComparer(GradientStop* a, GradientStop* b)
{
    return a->position() < b->position();
}

void LinearGradient::update(ComponentDirt value)
{
    // Do the stops need to be re-ordered?
    bool stopsChanged = hasDirt(value, ComponentDirt::Stops);
    if (stopsChanged)
    {
        std::sort(m_Stops.begin(), m_Stops.end(), stopsComparer);
    }

    bool worldTransformed = hasDirt(value, ComponentDirt::WorldTransform);

    bool paintsInWorldSpace = parent()->as<ShapePaint>()->pathSpace() == PathSpace::World;
    // We rebuild the gradient if the gradient is dirty or we paint in world
    // space and the world space transform has changed, or the local transform
    // has changed. Local transform changes when a stop moves in local space.
    bool rebuildGradient =
        hasDirt(value,
                ComponentDirt::Paint | ComponentDirt::RenderOpacity | ComponentDirt::Transform) ||
        (paintsInWorldSpace && worldTransformed);
    if (rebuildGradient)
    {
        Vec2D start(startX(), startY());
        Vec2D end(endX(), endY());
        // Check if we need to update the world space gradient (if there's no
        // shape container, presumably it's the artboard and we're already in
        // world).
        if (paintsInWorldSpace && m_ShapePaintContainer != nullptr)
        {
            // Get the start and end of the gradient in world coordinates (world
            // transform of the shape).
            const Mat2D& world = m_ShapePaintContainer->worldTransform();
            start = world * start;
            end = world * end;
        }

        // build up the color and positions lists
        const auto ro = opacity() * renderOpacity();
        const auto count = m_Stops.size();

        // need some temporary storage. Allocate enough for both arrays
        assert(sizeof(ColorInt) == sizeof(float));
        std::vector<ColorInt> storage(count * 2);
        ColorInt* colors = storage.data();
        float* stops = (float*)colors + count;

        for (size_t i = 0; i < count; ++i)
        {
            colors[i] = colorModulateOpacity(m_Stops[i]->colorValue(), ro);
            stops[i] = m_Stops[i]->position();
        }

        makeGradient(start, end, colors, stops, count);
    }
}

void LinearGradient::makeGradient(Vec2D start,
                                  Vec2D end,
                                  const ColorInt colors[],
                                  const float stops[],
                                  size_t count)
{
    auto factory = artboard()->factory();
    renderPaint()->shader(
        factory->makeLinearGradient(start.x, start.y, end.x, end.y, colors, stops, count));
}

void LinearGradient::markGradientDirty() { addDirt(ComponentDirt::Paint); }
void LinearGradient::markStopsDirty() { addDirt(ComponentDirt::Paint | ComponentDirt::Stops); }

void LinearGradient::renderOpacityChanged() { markGradientDirty(); }

void LinearGradient::startXChanged() { addDirt(ComponentDirt::Transform); }
void LinearGradient::startYChanged() { addDirt(ComponentDirt::Transform); }
void LinearGradient::endXChanged() { addDirt(ComponentDirt::Transform); }
void LinearGradient::endYChanged() { addDirt(ComponentDirt::Transform); }
void LinearGradient::opacityChanged() { markGradientDirty(); }

bool LinearGradient::internalIsTranslucent() const
{
    if (opacity() < 1)
    {
        return true;
    }
    for (const auto stop : m_Stops)
    {
        if (colorAlpha(stop->colorValue()) != 0xFF)
        {
            return true;
        }
    }
    return false; // all of our stops are opaque
}
