#include "rive/animation/linear_animation.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/animation/keyed_callback_reporter.hpp"
#include "rive/artboard.hpp"
#include "rive/importers/artboard_importer.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/math/math_types.hpp"
#include <cmath>

using namespace rive;

#ifdef TESTING
int LinearAnimation::deleteCount = 0;
#endif

LinearAnimation::LinearAnimation() {}

LinearAnimation::~LinearAnimation()
{
#ifdef TESTING
    deleteCount++;
#endif
}

StatusCode LinearAnimation::onAddedDirty(CoreContext* context)
{
    StatusCode status = StatusCode::Ok;
    std::vector<size_t> failedKeyedObjects;
    for (size_t i = 0; i < m_KeyedObjects.size(); ++i)
    {
        StatusCode code = m_KeyedObjects[i]->onAddedDirty(context);
        if (code != StatusCode::Ok)
        {
            failedKeyedObjects.push_back(i);
            if (status == StatusCode::Ok || status == StatusCode::MissingObject)
            {
                status = code;
            }
        }
    }

    // Failed keyed objects should not be applied later in animation playback.
    for (auto it = failedKeyedObjects.rbegin(); it != failedKeyedObjects.rend();
         ++it)
    {
        m_KeyedObjects.erase(m_KeyedObjects.begin() + *it);
    }

#ifdef WITH_RIVE_EDITOR
    // Coop-hydrated KeyedObjects run their own onAddedDirty in the
    // dispatcher's Pass 3 (editor_native/command_dispatcher.cpp); this
    // loop is redundant for arena-owned entries but cheap (vector is
    // empty on .riv-loaded animations).
    for (auto* object : m_EditorKeyedObjects)
    {
        object->onAddedDirty(context);
    }
#endif

    // Missing keyed objects are non-fatal at artboard init time.
    return status == StatusCode::MissingObject ? StatusCode::Ok : status;
}

StatusCode LinearAnimation::onAddedClean(CoreContext* context)
{
    StatusCode code;
    for (const auto& object : m_KeyedObjects)
    {
        if ((code = object->onAddedClean(context)) != StatusCode::Ok)
        {
            return code;
        }
    }
#ifdef WITH_RIVE_EDITOR
    for (auto* object : m_EditorKeyedObjects)
    {
        object->onAddedClean(context);
    }
#endif
    return StatusCode::Ok;
}

void LinearAnimation::addKeyedObject(std::unique_ptr<KeyedObject> object)
{
    m_KeyedObjects.push_back(std::move(object));
}

// `addKeyedObjectForEditor` and `clearEditorKeyedObjects` live in
// `editor_native/native/src/editor/animation/linear_animation_editor.cpp`
// — see the matching comment in `keyed_property.cpp`.

void LinearAnimation::apply(Artboard* artboard,
                            float time,
                            float mix,
                            const LinearAnimationInstance* context) const
{
    if (quantize())
    {
        float ffps = (float)fps();
        time = std::floor(time * ffps) / ffps;
    }
    for (const auto& object : m_KeyedObjects)
    {
        object->apply(artboard, time, mix, context);
    }
#ifdef WITH_RIVE_EDITOR
    for (auto* object : m_EditorKeyedObjects)
    {
        object->apply(artboard, time, mix, context);
    }
#endif
}

StatusCode LinearAnimation::import(ImportStack& importStack)
{
    auto artboardImporter =
        importStack.latest<ArtboardImporter>(ArtboardBase::typeKey);
    if (artboardImporter == nullptr)
    {
        return StatusCode::MissingObject;
    }
    artboardImporter->addAnimation(this);
    return Super::import(importStack);
}

float LinearAnimation::startSeconds() const
{
    return (enableWorkArea() ? (float)workStart() : 0.0f) / (float)fps();
}
float LinearAnimation::endSeconds() const
{
    return (float)(enableWorkArea() ? workEnd() : duration()) / (float)fps();
}

float LinearAnimation::startTime() const
{
    return (speed() >= 0) ? startSeconds() : endSeconds();
}
float LinearAnimation::startTime(float multiplier) const
{
    return ((speed() * multiplier) >= 0) ? startSeconds() : endSeconds();
}
float LinearAnimation::endTime() const
{
    return (speed() >= 0) ? endSeconds() : startSeconds();
}
float LinearAnimation::durationSeconds() const
{
    return std::abs(endSeconds() - startSeconds());
}

// Matches Dart modulus:
// https://api.dart.dev/stable/2.19.0/dart-core/double/operator_modulo.html
static float positiveMod(float value, float range)
{
    assert(range > 0.0f);
    return math::positive_mod(value, range);
}

float LinearAnimation::globalToLocalSeconds(float seconds) const
{
    switch (loop())
    {
        case Loop::oneShot:
            return seconds + startTime();
        case Loop::loop:
            return positiveMod(seconds, (durationSeconds())) + startTime();
        case Loop::pingPong:
            float localTime = positiveMod(seconds, (durationSeconds()));
            int direction = ((int)(seconds / (durationSeconds()))) % 2;
            return direction == 0 ? localTime + startTime()
                                  : endTime() - localTime;
    }
    RIVE_UNREACHABLE();
}

void LinearAnimation::reportKeyedCallbacks(KeyedCallbackReporter* reporter,
                                           float secondsFrom,
                                           float secondsTo,
                                           float speedDirection,
                                           bool fromPong) const
{
    float startingTime = startTime(speedDirection);
    bool isAtStartFrame = startingTime == secondsFrom;

    if (!isAtStartFrame || !fromPong)
    {
        for (const auto& object : m_KeyedObjects)
        {
            object->reportKeyedCallbacks(reporter,
                                         secondsFrom,
                                         secondsTo,
                                         isAtStartFrame);
        }
#ifdef WITH_RIVE_EDITOR
        for (auto* object : m_EditorKeyedObjects)
        {
            object->reportKeyedCallbacks(reporter,
                                         secondsFrom,
                                         secondsTo,
                                         isAtStartFrame);
        }
#endif
    }
}