#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/interpolating_keyframe.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/loop.hpp"
#include "rive/animation/keyed_callback_reporter.hpp"
#include "rive/assets/script_asset.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/profiler/profiler_macros.h"
#include "rive/scripted/scripted_interpolator.hpp"

#include <cmath>
#include <cassert>

using namespace rive;

LinearAnimationInstance::LinearAnimationInstance(
    const LinearAnimation* animation,
    ArtboardInstance* instance,
    float speedMultiplier) :
    Scene(instance),
    m_animation((assert(animation != nullptr), animation)),
    m_time((speedMultiplier >= 0) ? animation->startTime()
                                  : animation->endTime()),
    m_speedDirection((speedMultiplier >= 0) ? 1 : -1),
    m_totalTime(0.0f),
    m_lastTotalTime(0.0f),
    m_spilledTime(0.0f),
    m_direction(1)
{}

LinearAnimationInstance::LinearAnimationInstance(
    LinearAnimationInstance const& lhs) :
    Scene(lhs),
    m_animation(lhs.m_animation),
    m_time(lhs.m_time),
    m_speedDirection(lhs.m_speedDirection),
    m_totalTime(lhs.m_totalTime),
    m_lastTotalTime(lhs.m_lastTotalTime),
    m_spilledTime(lhs.m_spilledTime),
    m_direction(lhs.m_direction),
    m_didLoop(lhs.m_didLoop),
    m_loopValue(lhs.m_loopValue)
{}

LinearAnimationInstance::~LinearAnimationInstance()
{
    // Critical teardown order, mirroring the SMI pattern at
    // state_machine_instance.cpp:2011-2044: pull cloned data binds out of
    // the artboard and delete them BEFORE m_scriptedInterpolatorInstances
    // destroys the clones whose CustomPropertys are those binds' targets.
    // Without this, the next Artboard::updateDataBinds() (which runs every
    // frame from updatePass) reads through DataBind::target() into freed
    // memory.
    if (m_artboardInstance != nullptr)
    {
        for (auto* bind : m_clonedArtboardDataBinds)
        {
            m_artboardInstance->removeDataBind(bind);
            delete bind;
        }
    }
    m_clonedArtboardDataBinds.clear();
    // m_scriptedInterpolatorInstances destructs here via unique_ptr; safe now
    // that no DataBind still points at the clones' CustomPropertys.
}

// Returns a per-(this LAI, keyframe) stateful clone of the given shared
// ScriptedInterpolator. Mirrors StateMachineInstance::scriptedObjects but
// keyed by the keyframe pointer so distinct keyframes that share a script
// each get their own Lua `self` table. Lazily allocates the map and the
// clone on first hit; subsequent calls return the cached clone. Cleanup
// runs in ~LinearAnimationInstance via unique_ptr.
ScriptedInterpolator* LinearAnimationInstance::statefulInterpolator(
    const InterpolatingKeyFrame* keyframe,
    const ScriptedInterpolator* shared) const
{
    if (shared == nullptr || keyframe == nullptr)
    {
        return nullptr;
    }
    if (m_scriptedInterpolatorInstances == nullptr)
    {
        m_scriptedInterpolatorInstances = std::make_unique<
            std::unordered_map<const InterpolatingKeyFrame*,
                               std::unique_ptr<ScriptedInterpolator>>>();
    }
    auto& map = *m_scriptedInterpolatorInstances;
    auto it = map.find(keyframe);
    if (it != map.end())
    {
        return it->second.get();
    }

    // cloneScriptedObject is non-const on the source; the shared template is
    // logically read-only here so the const_cast is safe and matches the
    // ScriptedListenerAction pattern.
    auto* cloneAsObj =
        const_cast<ScriptedInterpolator*>(shared)->cloneScriptedObject(
            m_artboardInstance);
    if (cloneAsObj == nullptr)
    {
        return nullptr;
    }
    auto* clone = static_cast<ScriptedInterpolator*>(cloneAsObj);
    clone->dataContext(m_artboardInstance->dataContext());

    // Walk the clone's ScriptInputs to discover the binds cloneProperties
    // just parked on the artboard for this clone. The back-pointer is set
    // inside cloneProperties (scripted_object.cpp) immediately after
    // dataBindContainer->addDataBind(...). We track these so ~LAI can
    // removeDataBind + delete each one BEFORE the clone — whose
    // CustomProperty is the bind's target — is destroyed.
    for (auto* prop : clone->customProperties())
    {
        if (auto* input = ScriptInput::from(prop))
        {
            if (auto* bind = input->dataBind())
            {
                m_clonedArtboardDataBinds.push_back(bind);
            }
        }
    }

    // Late-binding safety net: reinit() inside cloneScriptedObject is a no-op
    // when scriptAsset() is null at clone time. If the asset became available
    // later (editor live-edit), init now. ensureScriptInitialized
    // short-circuits when already initialized so this stays cheap.
    if (clone->scriptAsset() != nullptr && !clone->userLuaInitDone())
    {
        clone->scriptAsset()->initScriptedObject(clone);
        clone->hydrateScriptInputs();
    }

    auto* raw = clone;
    map.emplace(keyframe, std::unique_ptr<ScriptedInterpolator>(clone));
    return raw;
}

bool LinearAnimationInstance::advanceAndApply(float seconds)
{
    RIVE_PROF_SCOPE_L(1)
    bool more = this->advance(seconds, this);
    this->apply();
    if (m_artboardInstance->advance(seconds))
    {
        more = true;
    }
    return more || keepGoing();
}

bool LinearAnimationInstance::advance(float elapsedSeconds,
                                      KeyedCallbackReporter* reporter)
{
    const LinearAnimation& animation = *m_animation;
    float deltaSeconds = elapsedSeconds * animation.speed() * m_direction;

    m_spilledTime = 0.0f;
    if (deltaSeconds == 0)
    {
        m_didLoop = false;
        return false;
    }

    m_lastTotalTime = m_totalTime;
    m_totalTime += std::abs(deltaSeconds);

    // NOTE:
    // do not track spilled time, if our one shot loop is already completed.
    // stop gap before we move spilled tracking into state machine logic.
    bool killSpilledTime = !this->keepGoing(elapsedSeconds);

    float lastTime = m_time;
    m_time += deltaSeconds;
    if (reporter != nullptr)
    {
        animation.reportKeyedCallbacks(reporter,
                                       lastTime,
                                       m_time,
                                       m_speedDirection,
                                       false);
    }

    float fps = (float)animation.fps();
    float frames = m_time * fps;
    float start =
        animation.enableWorkArea() ? (float)animation.workStart() : 0.0f;
    float end = animation.enableWorkArea() ? (float)animation.workEnd()
                                           : (float)animation.duration();
    float range = end - start;

    bool didLoop = false;

    // this has some issues when deltaSeconds is 0,
    // right now we basically assume we default to going forwards in that case
    //
    int direction = deltaSeconds < 0 ? -1 : 1;
    switch (loop())
    {
        case Loop::oneShot:
            if (direction == 1 && frames > end)
            {
                // Account for the time dilation or contraction applied in the
                // animation local time by its speed to calculate spilled time.
                // Calculate the ratio of the time excess by the total elapsed
                // time in local time (deltaFrames) and multiply the elapsed
                // time by it.
                auto deltaFrames = deltaSeconds * fps;
                auto spilledFramesRatio = (frames - end) / deltaFrames;
                m_spilledTime = spilledFramesRatio * elapsedSeconds;
                frames = (float)end;
                m_time = frames / fps;
                didLoop = true;
            }
            else if (direction == -1 && frames < start)
            {
                auto deltaFrames = std::abs(deltaSeconds * fps);
                auto spilledFramesRatio = (start - frames) / deltaFrames;
                m_spilledTime = spilledFramesRatio * elapsedSeconds;
                frames = (float)start;
                m_time = frames / fps;
                didLoop = true;
            }
            break;
        case Loop::loop:
            if (direction == 1 && frames >= end)
            {
                // How spilled time has to be calculated, given that local time
                // can be scaled to a factor of the regular time:
                // - for convenience, calculate the local elapsed time in frames
                // (deltaFrames)
                // - get the remainder of current frame position (frames) by
                // duration (range)
                // - use that remainder as the ratio of the original time that
                // was not consumed by the loop (spilledFramesRatio)
                // - multiply the original elapsedTime by the ratio to set the
                // spilled time
                auto deltaFrames = deltaSeconds * fps;
                auto remainder = std::fmod(frames - start, (float)range);
                auto spilledFramesRatio = remainder / deltaFrames;
                m_spilledTime = spilledFramesRatio * elapsedSeconds;
                frames = start + remainder;
                m_time = frames / fps;
                didLoop = true;
                if (reporter != nullptr)
                {
                    animation.reportKeyedCallbacks(reporter,
                                                   0.0f,
                                                   m_time,
                                                   m_speedDirection,
                                                   false);
                }
            }
            else if (direction == -1 && frames <= start)
            {
                auto deltaFrames = deltaSeconds * fps;
                auto remainder =
                    std::abs(std::fmod(start - frames, (float)range));
                auto spilledFramesRatio = std::abs(remainder / deltaFrames);
                m_spilledTime = spilledFramesRatio * elapsedSeconds;
                frames = end - remainder;
                m_time = frames / fps;
                didLoop = true;
                if (reporter != nullptr)
                {
                    animation.reportKeyedCallbacks(reporter,
                                                   end / (float)fps,
                                                   m_time,
                                                   m_speedDirection,
                                                   false);
                }
            }
            break;
        case Loop::pingPong:
            bool fromPong = true;
            while (true)
            {
                if (direction == 1 && frames >= end)
                {
                    m_spilledTime = (frames - end) / fps;
                    frames = end + (end - frames);
                    lastTime = end / (float)fps;
                }
                else if (direction == -1 && frames < start)
                {
                    m_spilledTime = (start - frames) / fps;
                    frames = start + (start - frames);
                    lastTime = start / (float)fps;
                }
                else
                {
                    // we're within the range, we can stop fixing. We do this in
                    // a loop to fix conditions when time has advanced so far
                    // that we've ping-ponged back and forth a few times in a
                    // single frame. We want to accomodate for this in cases
                    // where animations are not advanced on regular intervals.
                    break;
                }
                m_time = frames / fps;
                m_direction *= -1;
                direction *= -1;
                didLoop = true;
                if (reporter != nullptr)
                {
                    animation.reportKeyedCallbacks(reporter,
                                                   lastTime,
                                                   m_time,
                                                   m_speedDirection,
                                                   fromPong);
                }
                fromPong = !fromPong;
            }
            break;
    }

    if (killSpilledTime)
    {
        m_spilledTime = 0;
    }

    m_didLoop = didLoop;
    return this->keepGoing(elapsedSeconds);
}

void LinearAnimationInstance::time(float value)
{
    if (m_time == value)
    {
        return;
    }
    m_time = value;
    // Make sure to keep last and total in relative lockstep so state machines
    // can track change even when setting time.
    auto diff = m_totalTime - m_lastTotalTime;

    float start =
        (m_animation->enableWorkArea() ? (float)m_animation->workStart()
                                       : 0.0f) *
        (float)m_animation->fps();
    m_totalTime = value - start;
    m_lastTotalTime = m_totalTime - diff;

    // leaving this RIGHT now. but is this required? it kinda messes up
    // playing things backwards and seeking. what purpose does it solve?
    m_direction = 1;
}

void LinearAnimationInstance::reset(float speedMultiplier = 1.0)
{
    m_time = (speedMultiplier >= 0) ? m_animation->startTime()
                                    : m_animation->endTime();
}

uint32_t LinearAnimationInstance::fps() const { return m_animation->fps(); }

uint32_t LinearAnimationInstance::duration() const
{
    return m_animation->duration();
}

float LinearAnimationInstance::speed() const { return m_animation->speed(); }

float LinearAnimationInstance::startTime() const
{
    return m_animation->startTime();
}

std::string LinearAnimationInstance::name() const
{
    return m_animation->name();
}

bool LinearAnimationInstance::isTranslucent() const
{
    return m_artboardInstance->isTranslucent(this);
}

// Returns either the animation's default or overridden loop values
int LinearAnimationInstance::loopValue() const
{
    if (m_loopValue != -1)
    {
        return m_loopValue;
    }
    return m_animation->loopValue();
}

// Override the animation's loop value
void LinearAnimationInstance::loopValue(int value)
{
    if (m_loopValue == value)
    {
        return;
    }
    if (m_loopValue == -1 && m_animation->loopValue() == value)
    {
        return;
    }
    m_loopValue = value;
}

float LinearAnimationInstance::durationSeconds() const
{
    return m_animation->durationSeconds();
}

void LinearAnimationInstance::reportEvent(Event* event, float secondsDelay)
{
    const std::vector<Event*> events{event};
    notifyListeners(events);
}