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

using namespace rive;

LinearAnimationInstance::LinearAnimationInstance(const LinearAnimation* animation,
                                                 ArtboardInstance* instance) :
    Scene(instance),
    m_Animation(animation),
    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) {
    Counter::update(Counter::kLinearAnimationInstance, +1);
}

LinearAnimationInstance::LinearAnimationInstance(LinearAnimationInstance const& lhs) :
    Scene(lhs),
    m_Animation(lhs.m_Animation),
    m_Time(lhs.m_Time),
    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) {
    Counter::update(Counter::kLinearAnimationInstance, +1);
}

LinearAnimationInstance::~LinearAnimationInstance() {
    Counter::update(Counter::kLinearAnimationInstance, -1);
}

bool LinearAnimationInstance::advanceAndApply(float seconds) {
    bool more = this->advance(seconds);
    this->apply();
    m_ArtboardInstance->advance(seconds);
    return more;
}

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 = (float)end;
                m_Time = frames / fps;
                didLoop = true;
            } else if (m_Direction == -1 && frames < start) {
                keepGoing = false;
                m_SpilledTime = (start - frames) / fps;
                frames = (float)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, (float)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, (float)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;
}

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::startSeconds() const { return m_Animation->startSeconds(); }

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