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