#include "rive/animation/state_transition.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/layer_state_importer.hpp"
#include "rive/animation/layer_state.hpp"
#include "rive/animation/transition_condition.hpp"
#include "rive/animation/animation_state.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "rive/animation/state_machine_trigger.hpp"
#include "rive/animation/animation_state_instance.hpp"
#include "rive/animation/transition_trigger_condition.hpp"

using namespace rive;

StateTransition::~StateTransition() {
    for (auto condition : m_Conditions) {
        delete condition;
    }
}

StatusCode StateTransition::onAddedDirty(CoreContext* context) {
    StatusCode code;
    for (auto condition : m_Conditions) {
        if ((code = condition->onAddedDirty(context)) != StatusCode::Ok) {
            return code;
        }
    }
    return StatusCode::Ok;
}

StatusCode StateTransition::onAddedClean(CoreContext* context) {
    StatusCode code;
    for (auto condition : m_Conditions) {
        if ((code = condition->onAddedClean(context)) != StatusCode::Ok) {
            return code;
        }
    }
    return StatusCode::Ok;
}

StatusCode StateTransition::import(ImportStack& importStack) {
    auto stateImporter = importStack.latest<LayerStateImporter>(LayerState::typeKey);
    if (stateImporter == nullptr) {
        return StatusCode::MissingObject;
    }
    stateImporter->addTransition(this);
    return Super::import(importStack);
}

void StateTransition::addCondition(TransitionCondition* condition) {
    m_Conditions.push_back(condition);
}

float StateTransition::mixTime(const LayerState* stateFrom) const {
    if (duration() == 0) {
        return 0;
    }
    if ((transitionFlags() & StateTransitionFlags::DurationIsPercentage) ==
        StateTransitionFlags::DurationIsPercentage)
    {
        float animationDuration = 0.0f;
        if (stateFrom->is<AnimationState>()) {
            auto animation = stateFrom->as<AnimationState>()->animation();
            if (animation != nullptr) {
                animationDuration = animation->durationSeconds();
            }
        }
        return duration() / 100.0f * animationDuration;
    } else {
        return duration() / 1000.0f;
    }
}

float StateTransition::exitTimeSeconds(const LayerState* stateFrom, bool absolute) const {
    if ((transitionFlags() & StateTransitionFlags::ExitTimeIsPercentage) ==
        StateTransitionFlags::ExitTimeIsPercentage)
    {
        float animationDuration = 0.0f;
        float start = 0.0f;

        auto exitAnimation = exitTimeAnimation(stateFrom);
        if (exitAnimation != nullptr) {
            start = absolute ? exitAnimation->startSeconds() : 0.0f;
            animationDuration = exitAnimation->durationSeconds();
        }

        return start + exitTime() / 100.0f * animationDuration;
    }
    return exitTime() / 1000.0f;
}

const LinearAnimationInstance*
StateTransition::exitTimeAnimationInstance(const StateInstance* from) const {
    return from != nullptr && from->state()->is<AnimationState>()
               ? static_cast<const AnimationStateInstance*>(from)->animationInstance()
               : nullptr;
}

const LinearAnimation* StateTransition::exitTimeAnimation(const LayerState* from) const {
    return from != nullptr && from->is<AnimationState>() ? from->as<AnimationState>()->animation()
                                                         : nullptr;
}

AllowTransition
StateTransition::allowed(StateInstance* stateFrom, Span<SMIInput*> inputs, bool ignoreTriggers) const {
    if (isDisabled()) {
        return AllowTransition::no;
    }

    for (auto condition : m_Conditions) {
        // N.B. state machine instance sanitizes these for us...
        auto input = inputs[condition->inputId()];

        if ((ignoreTriggers && condition->is<TransitionTriggerCondition>()) ||
            !condition->evaluate(input)) {
            return AllowTransition::no;
        }
    }

    if (enableExitTime()) {
        auto exitAnimation = exitTimeAnimationInstance(stateFrom);
        if (exitAnimation != nullptr) {
            // Exit time is specified in a value less than a single loop, so we
            // want to allow exiting regardless of which loop we're on. To do
            // that we bring the exit time up to the loop our lastTime is at.
            auto lastTime = exitAnimation->lastTotalTime();
            auto time = exitAnimation->totalTime();
            auto exitTime = exitTimeSeconds(stateFrom->state());
            auto animationFrom = exitAnimation->animation();
            auto duration = animationFrom->durationSeconds();

            // TODO: there are some considerations to have when exit time is
            // combined with another condition (like trigger)
            //   - not sure how to get this to make sense with pingPing
            //   animations
            //   - also if exit time is, say 50% on a loop, this will be happy
            //   to fire
            //       - when time is anywhere in 50%-100%, 150%-200%. as opposed
            //       to just at 50%
            //       .... makes you wonder if we need some kind of exit
            //       after/exit before time
            //       .... but i suspect that will introduce some more issues?

            // There's only one iteration in oneShot,
            if (exitTime <= duration && animationFrom->loop() != Loop::oneShot) {
                // Get exit time relative to the loop lastTime was in.
                exitTime += std::floor(lastTime / duration) * duration;
            }

            if (time < exitTime) {
                return AllowTransition::waitingForExit;
            }
        }
    }
    return AllowTransition::yes;
}

bool StateTransition::applyExitCondition(StateInstance* from) const {
    // Hold exit time when the user has set to pauseOnExit on this condition
    // (only valid when exiting from an Animation).
    bool useExitTime = enableExitTime() && (from != nullptr && from->state()->is<AnimationState>());
    if (pauseOnExit() && useExitTime) {
        static_cast<AnimationStateInstance*>(from)->animationInstance()->time(
            exitTimeSeconds(from->state(), true));
        return true;
    }
    return useExitTime;
}