#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);
    }

    // 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;
        }
    }
    return StatusCode::Ok;
}

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

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);
    }
}

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);
        }
    }
}