#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/loop.hpp"
#include <cmath>

using namespace rive;

LinearAnimationInstance::LinearAnimationInstance(const LinearAnimation* animation,
                                                 Artboard* instance) :
    m_Animation(animation),
    m_ArtboardInstance(instance),
    m_Time(animation->enableWorkArea() ? (float)animation->workStart() / animation->fps() : 0),
    m_TotalTime(0.0f),
    m_LastTotalTime(0.0f),
    m_SpilledTime(0.0f),
    m_Direction(1) {}

bool LinearAnimationInstance::advance(float elapsedSeconds) {
    const LinearAnimation& animation = *m_Animation;
    m_Time += elapsedSeconds * animation.speed() * m_Direction;
    m_LastTotalTime = m_TotalTime;
    m_TotalTime += elapsedSeconds;

    int fps = animation.fps();

    float frames = m_Time * fps;

    int start = animation.enableWorkArea() ? animation.workStart() : 0;
    int end = animation.enableWorkArea() ? animation.workEnd() : animation.duration();
    int range = end - start;

    bool keepGoing = true;
    bool didLoop = false;
    m_SpilledTime = 0.0f;

    switch (loop()) {
        case Loop::oneShot:
            if (m_Direction == 1 && frames > end) {
                keepGoing = false;
                m_SpilledTime = (frames - end) / fps;
                frames = end;
                m_Time = frames / fps;
                didLoop = true;
            } else if (m_Direction == -1 && frames < start) {
                keepGoing = false;
                m_SpilledTime = (start - frames) / fps;
                frames = start;
                m_Time = frames / fps;
                didLoop = true;
            }
            break;
        case Loop::loop:
            if (m_Direction == 1 && frames >= end) {
                m_SpilledTime = (frames - end) / fps;
                frames = m_Time * fps;
                frames = start + std::fmod(frames - start, range);

                m_Time = frames / fps;
                didLoop = true;
            } else if (m_Direction == -1 && frames <= start) {

                m_SpilledTime = (start - frames) / fps;
                frames = m_Time * fps;
                frames = end - std::abs(std::fmod(start - frames, range));
                m_Time = frames / fps;
                didLoop = true;
            }
            break;
        case Loop::pingPong:
            while (true) {
                if (m_Direction == 1 && frames >= end) {
                    m_SpilledTime = (frames - end) / fps;
                    m_Direction = -1;
                    frames = end + (end - frames);
                    m_Time = frames / fps;
                    didLoop = true;
                } else if (m_Direction == -1 && frames < start) {
                    m_SpilledTime = (start - frames) / fps;
                    m_Direction = 1;
                    frames = start + (start - frames);
                    m_Time = frames / fps;
                    didLoop = true;
                } 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;
                }
            }
            break;
    }

    m_DidLoop = didLoop;
    return keepGoing;
}

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;

    int start = (m_Animation->enableWorkArea() ? m_Animation->workStart() : 0) * 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;
}

// Returns either the animation's default or overridden loop values
int LinearAnimationInstance::loopValue() {
    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(); }