#include "rive/animation/state_machine_instance.hpp"
#include "rive/animation/state_machine_input.hpp"
#include "rive/animation/state_machine_bool.hpp"
#include "rive/animation/state_machine_number.hpp"
#include "rive/animation/state_machine_trigger.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "rive/animation/state_machine.hpp"
#include "rive/animation/state_machine_layer.hpp"
#include "rive/animation/any_state.hpp"
#include "rive/animation/entry_state.hpp"
#include "rive/animation/state_transition.hpp"
#include "rive/animation/transition_condition.hpp"
#include "rive/animation/animation_state.hpp"
#include "rive/animation/state_instance.hpp"
#include "rive/animation/animation_state_instance.hpp"
#include "rive/animation/state_machine_listener.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/math/aabb.hpp"
#include "rive/math/hit_test.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/nested_animation.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include "rive/rive_counter.hpp"
#include <unordered_map>

using namespace rive;
namespace rive {
class StateMachineLayerInstance {
private:
    static const int maxIterations = 100;
    const StateMachineLayer* m_Layer = nullptr;
    ArtboardInstance* m_ArtboardInstance = nullptr;

    StateInstance* m_AnyStateInstance = nullptr;
    StateInstance* m_CurrentState = nullptr;
    StateInstance* m_StateFrom = nullptr;

    // const LayerState* m_CurrentState = nullptr;
    // const LayerState* m_StateFrom = nullptr;
    const StateTransition* m_Transition = nullptr;

    bool m_HoldAnimationFrom = false;
    // LinearAnimationInstance* m_AnimationInstance = nullptr;
    // LinearAnimationInstance* m_AnimationInstanceFrom = nullptr;
    float m_Mix = 1.0f;
    float m_MixFrom = 1.0f;
    bool m_StateChangedOnAdvance = false;

    bool m_WaitingForExit = false;
    /// Used to ensure a specific animation is applied on the next apply.
    const LinearAnimation* m_HoldAnimation = nullptr;
    float m_HoldTime = 0.0f;

public:
    ~StateMachineLayerInstance() {
        delete m_AnyStateInstance;
        delete m_CurrentState;
        delete m_StateFrom;
    }

    void init(const StateMachineLayer* layer, ArtboardInstance* instance) {
        m_ArtboardInstance = instance;
        assert(m_Layer == nullptr);
        m_AnyStateInstance = layer->anyState()->makeInstance(instance).release();
        m_Layer = layer;
        changeState(m_Layer->entryState());
    }

    void updateMix(float seconds) {
        if (m_Transition != nullptr && m_StateFrom != nullptr && m_Transition->duration() != 0) {
            m_Mix = std::min(
                1.0f,
                std::max(0.0f, (m_Mix + seconds / m_Transition->mixTime(m_StateFrom->state()))));
        } else {
            m_Mix = 1.0f;
        }
    }

    bool advance(/*Artboard* artboard, */ float seconds, Span<SMIInput*> inputs) {
        m_StateChangedOnAdvance = false;

        if (m_CurrentState != nullptr) {
            m_CurrentState->advance(seconds, inputs);
        }

        updateMix(seconds);

        if (m_StateFrom != nullptr && m_Mix < 1.0f && !m_HoldAnimationFrom) {
            // This didn't advance during our updateState, but it should now
            // that we realize we need to mix it in.
            m_StateFrom->advance(seconds, inputs);
        }

        for (int i = 0; updateState(inputs, i != 0); i++) {
            apply();

            if (i == maxIterations) {
                fprintf(stderr, "StateMachine exceeded max iterations.\n");
                return false;
            }
        }

        apply();

        return m_Mix != 1.0f || m_WaitingForExit ||
               (m_CurrentState != nullptr && m_CurrentState->keepGoing());
    }

    bool isTransitioning() {
        return m_Transition != nullptr && m_StateFrom != nullptr && m_Transition->duration() != 0 &&
               m_Mix < 1.0f;
    }

    bool updateState(Span<SMIInput*> inputs, bool ignoreTriggers) {
        // Don't allow changing state while a transition is taking place
        // (we're mixing one state onto another).
        if (isTransitioning()) {
            return false;
        }

        m_WaitingForExit = false;

        if (tryChangeState(m_AnyStateInstance, inputs, ignoreTriggers)) {
            return true;
        }

        return tryChangeState(m_CurrentState, inputs, ignoreTriggers);
    }

    bool changeState(const LayerState* stateTo) {
        if ((m_CurrentState == nullptr ? nullptr : m_CurrentState->state()) == stateTo) {
            return false;
        }
        m_CurrentState =
            stateTo == nullptr ? nullptr : stateTo->makeInstance(m_ArtboardInstance).release();
        return true;
    }

    bool tryChangeState(StateInstance* stateFromInstance,
                        Span<SMIInput*> inputs,
                        bool ignoreTriggers) {
        if (stateFromInstance == nullptr) {
            return false;
        }
        auto stateFrom = stateFromInstance->state();
        auto outState = m_CurrentState;
        for (size_t i = 0, length = stateFrom->transitionCount(); i < length; i++) {
            auto transition = stateFrom->transition(i);
            auto allowed = transition->allowed(stateFromInstance, inputs, ignoreTriggers);
            if (allowed == AllowTransition::yes && changeState(transition->stateTo())) {
                m_StateChangedOnAdvance = true;
                // state actually has changed
                m_Transition = transition;
                if (m_StateFrom != m_AnyStateInstance) {
                    // Old state from is done.
                    delete m_StateFrom;
                }
                m_StateFrom = outState;

                // If we had an exit time and wanted to pause on exit, make
                // sure to hold the exit time. Delegate this to the
                // transition by telling it that it was completed.
                if (outState != nullptr && transition->applyExitCondition(outState)) {
                    // Make sure we apply this state. This only returns true
                    // when it's an animation state instance.
                    auto instance =
                        static_cast<AnimationStateInstance*>(m_StateFrom)->animationInstance();

                    m_HoldAnimation = instance->animation();
                    m_HoldTime = instance->time();
                }
                m_MixFrom = m_Mix;

                // Keep mixing last animation that was mixed in.
                if (m_Mix != 0.0f) {
                    m_HoldAnimationFrom = transition->pauseOnExit();
                }
                if (m_StateFrom != nullptr && m_StateFrom->state()->is<AnimationState>() &&
                    m_CurrentState != nullptr)
                {
                    auto instance =
                        static_cast<AnimationStateInstance*>(m_StateFrom)->animationInstance();

                    auto spilledTime = instance->spilledTime();
                    m_CurrentState->advance(spilledTime, inputs);
                }
                m_Mix = 0.0f;
                updateMix(0.0f);
                m_WaitingForExit = false;
                return true;
            } else if (allowed == AllowTransition::waitingForExit) {
                m_WaitingForExit = true;
            }
        }
        return false;
    }

    void apply(/*Artboard* artboard*/) {
        if (m_HoldAnimation != nullptr) {
            m_HoldAnimation->apply(m_ArtboardInstance, m_HoldTime, m_MixFrom);
            m_HoldAnimation = nullptr;
        }

        if (m_StateFrom != nullptr && m_Mix < 1.0f) {
            m_StateFrom->apply(m_MixFrom);
        }
        if (m_CurrentState != nullptr) {
            m_CurrentState->apply(m_Mix);
        }
    }

    bool stateChangedOnAdvance() const { return m_StateChangedOnAdvance; }

    const LayerState* currentState() {
        return m_CurrentState == nullptr ? nullptr : m_CurrentState->state();
    }

    const LinearAnimationInstance* currentAnimation() const {
        if (m_CurrentState == nullptr || !m_CurrentState->state()->is<AnimationState>()) {
            return nullptr;
        }
        return static_cast<AnimationStateInstance*>(m_CurrentState)->animationInstance();
    }
};

/// Representation of a Shape from the Artboard Instance and all the listeners it
/// triggers. Allows tracking hover and performing hit detection only once on
/// shapes that trigger multiple listeners.
class HitShape {
private:
    Shape* m_Shape;

public:
    Shape* shape() const { return m_Shape; }
    HitShape(Shape* shape) : m_Shape(shape) {}
    bool isHovered = false;
    std::vector<const StateMachineListener*> listeners;
};
} // namespace rive

void StateMachineInstance::updateListeners(Vec2D position, ListenerType hitType) {
    if (m_ArtboardInstance->frameOrigin()) {
        position -= Vec2D(m_ArtboardInstance->originX() * m_ArtboardInstance->width(),
                          m_ArtboardInstance->originY() * m_ArtboardInstance->height());
    }

    const float hitRadius = 2;
    auto hitArea = AABB(position.x - hitRadius,
                        position.y - hitRadius,
                        position.x + hitRadius,
                        position.y + hitRadius)
                       .round();

    for (const auto& hitShape : m_HitShapes) {

        // TODO: quick reject.

        bool isOver = hitShape->shape()->hitTest(hitArea);

        bool hoverChange = hitShape->isHovered != isOver;
        hitShape->isHovered = isOver;

        // iterate all listeners associated with this hit shape
        for (auto listener : hitShape->listeners) {
            // Always update hover states regardless of which specific listener type
            // we're trying to trigger.
            if (hoverChange) {
                if (isOver && listener->listenerType() == ListenerType::enter) {
                    listener->performChanges(this, position);
                    markNeedsAdvance();
                } else if (!isOver && listener->listenerType() == ListenerType::exit) {
                    listener->performChanges(this, position);
                    markNeedsAdvance();
                }
            }
            if (isOver && hitType == listener->listenerType()) {
                listener->performChanges(this, position);
                markNeedsAdvance();
            }
        }
    }

    // TODO: store a hittable abstraction for HitShape and NestedArtboard that
    // can be sorted by drawOrder so they can be iterated in one loop and early
    // out if any hit stops propagation (also require the ability to mark a hit
    // as able to stop propagation)
    for (auto nestedArtboard : m_HitNestedArtboards) {
        Vec2D nestedPosition;
        if (!nestedArtboard->worldToLocal(position, &nestedPosition)) {
            // Mounted artboard isn't ready or has a 0 scale transform.
            continue;
        }

        for (auto nestedAnimation : nestedArtboard->nestedAnimations()) {
            if (nestedAnimation->is<NestedStateMachine>()) {
                auto nestedStateMachine = nestedAnimation->as<NestedStateMachine>();
                switch (hitType) {
                    case ListenerType::down: nestedStateMachine->pointerDown(nestedPosition); break;
                    case ListenerType::up: nestedStateMachine->pointerUp(nestedPosition); break;
                    case ListenerType::move: nestedStateMachine->pointerMove(nestedPosition); break;
                    case ListenerType::enter:
                    case ListenerType::exit: break;
                }
            }
        }
    }
}

void StateMachineInstance::pointerMove(Vec2D position) {
    updateListeners(position, ListenerType::move);
}
void StateMachineInstance::pointerDown(Vec2D position) {
    updateListeners(position, ListenerType::down);
}
void StateMachineInstance::pointerUp(Vec2D position) {
    updateListeners(position, ListenerType::up);
}

StateMachineInstance::StateMachineInstance(const StateMachine* machine,
                                           ArtboardInstance* instance) :
    Scene(instance), m_Machine(machine) {
    Counter::update(Counter::kStateMachineInstance, +1);

    const auto count = machine->inputCount();
    m_InputInstances.resize(count);
    for (size_t i = 0; i < count; i++) {
        auto input = machine->input(i);
        if (input == nullptr) {
            continue;
        }
        switch (input->coreType()) {
            case StateMachineBool::typeKey:
                m_InputInstances[i] = new SMIBool(input->as<StateMachineBool>(), this);
                break;
            case StateMachineNumber::typeKey:
                m_InputInstances[i] = new SMINumber(input->as<StateMachineNumber>(), this);
                break;
            case StateMachineTrigger::typeKey:
                m_InputInstances[i] = new SMITrigger(input->as<StateMachineTrigger>(), this);
                break;
            default:
                // Sanity check.
                break;
        }
    }

    m_LayerCount = machine->layerCount();
    m_Layers = new StateMachineLayerInstance[m_LayerCount];
    for (size_t i = 0; i < m_LayerCount; i++) {
        m_Layers[i].init(machine->layer(i), m_ArtboardInstance);
    }

    // Initialize listeners. Store a lookup table of shape id to hit shape
    // representation (an object that stores all the listeners triggered by the
    // shape producing a listener).
    std::unordered_map<uint32_t, HitShape*> hitShapeLookup;
    for (std::size_t i = 0; i < machine->listenerCount(); i++) {
        auto listener = machine->listener(i);

        // Iterate actual leaf hittable shapes tied to this listener and resolve
        // corresponding ones in the artboard instance.
        for (auto id : listener->hitShapeIds()) {
            HitShape* hitShape;
            auto itr = hitShapeLookup.find(id);
            if (itr == hitShapeLookup.end()) {
                auto shape = m_ArtboardInstance->resolve(id);
                if (shape != nullptr && shape->is<Shape>()) {
                    auto hs = std::make_unique<HitShape>(shape->as<Shape>());
                    hitShapeLookup[id] = hitShape = hs.get();
                    m_HitShapes.push_back(std::move(hs));
                } else {
                    // No object or not a shape...
                    continue;
                }
            } else {
                hitShape = itr->second;
            }
            hitShape->listeners.push_back(listener);
        }
    }

    for (auto nestedArtboard : instance->nestedArtboards()) {
        if (nestedArtboard->hasNestedStateMachines()) {
            m_HitNestedArtboards.push_back(nestedArtboard);
        }
    }
}

StateMachineInstance::~StateMachineInstance() {
    for (auto inst : m_InputInstances) {
        delete inst;
    }
    delete[] m_Layers;

    Counter::update(Counter::kStateMachineInstance, -1);
}

bool StateMachineInstance::advance(float seconds) {
    m_NeedsAdvance = false;
    for (size_t i = 0; i < m_LayerCount; i++) {
        if (m_Layers[i].advance(seconds, m_InputInstances)) {
            m_NeedsAdvance = true;
        }
    }

    for (auto inst : m_InputInstances) {
        inst->advanced();
    }

    return m_NeedsAdvance;
}

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

void StateMachineInstance::markNeedsAdvance() { m_NeedsAdvance = true; }
bool StateMachineInstance::needsAdvance() const { return m_NeedsAdvance; }

std::string StateMachineInstance::name() const { return m_Machine->name(); }

SMIInput* StateMachineInstance::input(size_t index) const {
    if (index < m_InputInstances.size()) {
        return m_InputInstances[index];
    }
    return nullptr;
}

template <typename SMType, typename InstType>
InstType* StateMachineInstance::getNamedInput(const std::string& name) const {
    for (const auto inst : m_InputInstances) {
        auto input = inst->input();
        if (input->is<SMType>() && input->name() == name) {
            return static_cast<InstType*>(inst);
        }
    }
    return nullptr;
}

SMIBool* StateMachineInstance::getBool(const std::string& name) const {
    return getNamedInput<StateMachineBool, SMIBool>(name);
}
SMINumber* StateMachineInstance::getNumber(const std::string& name) const {
    return getNamedInput<StateMachineNumber, SMINumber>(name);
}
SMITrigger* StateMachineInstance::getTrigger(const std::string& name) const {
    return getNamedInput<StateMachineTrigger, SMITrigger>(name);
}

size_t StateMachineInstance::stateChangedCount() const {
    size_t count = 0;
    for (size_t i = 0; i < m_LayerCount; i++) {
        if (m_Layers[i].stateChangedOnAdvance()) {
            count++;
        }
    }
    return count;
}

const LayerState* StateMachineInstance::stateChangedByIndex(size_t index) const {
    size_t count = 0;
    for (size_t i = 0; i < m_LayerCount; i++) {
        if (m_Layers[i].stateChangedOnAdvance()) {
            if (count == index) {
                return m_Layers[i].currentState();
            }
            count++;
        }
    }
    return nullptr;
}

size_t StateMachineInstance::currentAnimationCount() const {
    size_t count = 0;
    for (size_t i = 0; i < m_LayerCount; i++) {
        if (m_Layers[i].currentAnimation() != nullptr) {
            count++;
        }
    }
    return count;
}

const LinearAnimationInstance* StateMachineInstance::currentAnimationByIndex(size_t index) const {
    size_t count = 0;
    for (size_t i = 0; i < m_LayerCount; i++) {
        if (m_Layers[i].currentAnimation() != nullptr) {
            if (count == index) {
                return m_Layers[i].currentAnimation();
            }
            count++;
        }
    }
    return nullptr;
}
