#include "rive/animation/animation_reset.hpp"
#include "rive/animation/animation_reset_factory.hpp"
#include "rive/animation/animation_state_instance.hpp"
#include "rive/animation/animation_state.hpp"
#include "rive/animation/any_state.hpp"
#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/animation/keyframe.hpp"
#include "rive/animation/keyframe_double.hpp"
#include "rive/animation/keyframe_color.hpp"
#include "rive/animation/keyframe_bool.hpp"
#include "rive/animation/keyframe_string.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/animation/keyed_property.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/data_bind/bindable_property_number.hpp"
#include "rive/data_bind/bindable_property_color.hpp"
#include "rive/data_bind/bindable_property_boolean.hpp"
#include "rive/data_bind/bindable_property_string.hpp"
#include "rive/data_bind/converters/data_converter.hpp"
#include "rive/animation/entry_state.hpp"
#include "rive/animation/exit_state.hpp"
#include "rive/animation/layer_state_flags.hpp"
#include "rive/animation/nested_linear_animation.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include "rive/animation/scripted_transition_condition.hpp"
#include "rive/animation/state_instance.hpp"
#include "rive/animation/state_machine_bool.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "rive/animation/state_machine_input.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/animation/state_machine_layer.hpp"
#include "rive/animation/listener_invocation.hpp"
#include "rive/animation/state_machine_listener.hpp"
#include "rive/animation/state_machine_listener_single.hpp"
#include "rive/animation/state_machine_number.hpp"
#include "rive/animation/state_machine_trigger.hpp"
#include "rive/animation/state_machine.hpp"
#include "rive/animation/state_transition.hpp"
#include "rive/animation/listener_action.hpp"
#include "rive/animation/listener_types/listener_input_type_viewmodel.hpp"
#include "rive/animation/scripted_listener_action.hpp"
#include "rive/animation/transition_condition.hpp"
#include "rive/animation/transition_comparator.hpp"
#include "rive/animation/transition_property_viewmodel_comparator.hpp"
#include "rive/animation/transition_viewmodel_condition.hpp"
#include "rive/animation/state_machine_fire_event.hpp"
#include "rive/viewmodel/viewmodel_instance_trigger.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/constraints/draggable_constraint.hpp"
#include "rive/data_bind/data_bind_context.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/context/context_value.hpp"
#include "rive/data_bind/data_values/data_value_number.hpp"
#include "rive/data_bind_flags.hpp"
#include "rive/event_report.hpp"
#include "rive/hit_result.hpp"
#include "rive/listener_group.hpp"
#include "rive/math/aabb.hpp"
#include "rive/math/random.hpp"
#include "rive/math/hit_test.hpp"
#include "rive/nested_animation.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/process_event_result.hpp"
#include "rive/scripted/scripted_drawable.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/text/text.hpp"
#include "rive/math/math_types.hpp"
#include "rive/audio_event.hpp"
#include "rive/dirtyable.hpp"
#include "rive/profiler/profiler_macros.h"
#include "rive/text/text_input.hpp"
#include "rive/refcnt.hpp"
#include "rive/animation/focus_listener_group.hpp"
#include "rive/animation/text_input_listener_group.hpp"
#include "rive/animation/listener_types/listener_input_type_event.hpp"
#include "rive/focus_data.hpp"
#include "rive/node.hpp"
#include "rive/semantic/semantic_data.hpp"
#include "rive/view_model_type.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include "rive/file.hpp"
#include "rive/data_bind/data_context.hpp"
#include <array>
#include <memory>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <cmath>

using namespace rive;

#ifdef RIVE_MICROPROFILE
#include "rive/profiler/rive_profile.hpp"
static std::string getStateName(const StateInstance* stateInstance)
{
    if (stateInstance == nullptr)
    {
        return "(null)";
    }
    auto state = stateInstance->state();
    if (state->is<AnimationState>())
    {
        auto anim = state->as<AnimationState>()->animation();
        return anim != nullptr ? anim->name() : "Animation";
    }
    if (state->is<EntryState>())
    {
        return "Entry";
    }
    if (state->is<ExitState>())
    {
        return "Exit";
    }
    if (state->is<AnyState>())
    {
        return "Any";
    }
    return "Blend";
}
#endif

namespace rive
{
namespace
{
constexpr std::array<ListenerType, 9> kPointerHitListenerTypes = {
    ListenerType::enter,
    ListenerType::exit,
    ListenerType::down,
    ListenerType::up,
    ListenerType::move,
    ListenerType::click,
    ListenerType::dragStart,
    ListenerType::dragEnd,
    ListenerType::drag,
};
} // namespace

class StateMachineLayerInstance
{
public:
    ~StateMachineLayerInstance()
    {
        delete m_anyStateInstance;
        delete m_currentState;
        delete m_stateFrom;
    }

    void init(StateMachineInstance* stateMachineInstance,
              const StateMachineLayer* layer,
              ArtboardInstance* instance)
    {

        if (File::deterministicMode)
        {
            srand((unsigned int)1);
        }
        else
        {
            auto now = std::chrono::high_resolution_clock::now();
            auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(
                             now.time_since_epoch())
                             .count();
            srand((unsigned int)nanos);
        }
        m_stateMachineInstance = stateMachineInstance;
        m_artboardInstance = instance;
        assert(m_layer == nullptr);
        m_anyStateInstance =
            layer->anyState()->makeInstance(instance).release();
        stateMachineInstance->buildStateKeyFrameBinds(m_anyStateInstance);
        m_layer = layer;
        changeState(m_layer->entryState());
    }

    void resetState()
    {
        if (m_stateFrom != m_anyStateInstance && m_stateFrom != m_currentState)
        {
            m_stateMachineInstance->removeStateKeyFrameBinds(m_stateFrom);
            delete m_stateFrom;
        }
        m_stateFrom = nullptr;
        if (m_currentState != m_anyStateInstance)
        {
            m_stateMachineInstance->removeStateKeyFrameBinds(m_currentState);
            delete m_currentState;
        }
        m_currentState = nullptr;
        changeState(m_layer->entryState());
    }

    void updateMix(float seconds)
    {
        if (m_transition != nullptr && m_stateFrom != nullptr &&
            resolvedDuration() != 0)
        {
            auto mixTime = resolvedMixTime();
            if (mixTime == 0.0f)
            {
                m_mix = 1.0f;
            }
            else
            {
                m_mix =
                    std::min(1.0f, std::max(0.0f, (m_mix + seconds / mixTime)));
            }
            if (m_mix == 1.0f && !m_transitionCompleted)
            {
                m_transitionCompleted = true;
                clearAnimationReset();
                fireEvents(StateMachineFireOccurance::atEnd,
                           m_transition->events());
                performListenerActions(StateMachineFireOccurance::atEnd,
                                       m_transition->listenerActions());
            }
        }
        else
        {
            m_mix = 1.0f;
        }
    }

    bool advance(float seconds, bool newFrame)
    {
        if (newFrame)
        {
            m_stateMachineChangedOnAdvance = false;
        }
        m_currentState->advance(seconds, m_stateMachineInstance);
        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, m_stateMachineInstance);
        }

        apply();

        bool changedState = false;

        for (int i = 0; updateState(); i++)
        {
            changedState = true;
            apply();

            if (i == maxIterations)
            {
                auto stateMachineName =
                    m_stateMachineInstance->stateMachine() == nullptr
                        ? "[SM Not found]"
                        : m_stateMachineInstance->stateMachine()
                              ->name()
                              .c_str();
                auto layerName = m_layer == nullptr ? "[LY Not found]"
                                                    : m_layer->name().c_str();
                auto artboardName =
                    m_stateMachineInstance->artboard() == nullptr
                        ? "[AB Not found]"
                        : m_stateMachineInstance->artboard()->name().c_str();
                fprintf(stderr,
                        "%s StateMachine exceeded max iterations in layer %s "
                        "on artboard %s\n",
                        stateMachineName,
                        layerName,
                        artboardName);
                return false;
            }
        }

        m_currentState->clearSpilledTime();

        return changedState || m_mix != 1.0f || m_waitingForExit ||
               (m_currentState != nullptr && m_currentState->keepGoing());
    }

    /// Returns the per-instance transition duration, resolving any data
    /// binding override. Falls back to the shared definition value when
    /// no binding exists.
    uint32_t resolvedDuration() const
    {
        if (m_transitionDurationProperty != nullptr)
        {
            float val = m_transitionDurationProperty->propertyValue();
            return val < 0 ? 0 : static_cast<uint32_t>(std::round(val));
        }
        return m_transition->duration();
    }

    /// Computes the mix time using the per-instance resolved duration.
    float resolvedMixTime() const
    {
        auto dur = resolvedDuration();
        if (dur == 0)
        {
            return 0;
        }
        if (m_transition->durationIsPercentage())
        {
            float animationDuration = 0.0f;
            auto state = m_stateFrom->state();
            if (state->is<AnimationState>())
            {
                auto animation = state->as<AnimationState>()->animation();
                if (animation != nullptr)
                {
                    animationDuration = animation->durationSeconds();
                }
            }
            return (float)dur / 100.0f * animationDuration;
        }
        return (float)dur / 1000.0f;
    }

    bool isTransitioning()
    {
        return m_transition != nullptr && m_stateFrom != nullptr &&
               resolvedDuration() != 0 && m_mix < 1.0f;
    }

    bool updateState()
    {
        // Don't allow changing state while a transition is taking place
        // (we're mixing one state onto another) if enableEarlyExit is not true.
        if (isTransitioning() && !m_transition->enableEarlyExit())
        {
            return false;
        }

        m_waitingForExit = false;

        if (tryChangeState(m_anyStateInstance))
        {
            return true;
        }

        return tryChangeState(m_currentState);
    }

    void fireEvents(StateMachineFireOccurance occurs,
                    const std::vector<StateMachineFireAction*>& fireEvents)
    {
        for (auto event : fireEvents)
        {
            if (event->occurs() == occurs)
            {
                event->perform(m_stateMachineInstance);
            }
        }
    }

    void performListenerActions(
        StateMachineFireOccurance occurs,
        const std::vector<std::unique_ptr<ListenerAction>>& listenerActions)
    {
        for (const auto& action : listenerActions)
        {
            if (action->matchesScheduledOccurrence(occurs))
            {
                action->perform(m_stateMachineInstance,
                                ListenerInvocation::none());
            }
        }
    }

    bool canChangeState(const LayerState* stateTo)
    {
        return !(
            (m_currentState == nullptr ? nullptr : m_currentState->state()) ==
            stateTo);
    }

    double randomValue() { return RandomProvider::generateRandomFloat(); }

    void changeState(const LayerState* stateTo)
    {
        if ((m_currentState == nullptr ? nullptr : m_currentState->state()) ==
            stateTo)
        {
            return;
        }

        // Fire end events for the state we're changing from.
        if (m_currentState != nullptr)
        {
            fireEvents(StateMachineFireOccurance::atEnd,
                       m_currentState->state()->events());
            performListenerActions(StateMachineFireOccurance::atEnd,
                                   m_currentState->state()->listenerActions());
        }

        m_currentState =
            stateTo == nullptr
                ? nullptr
                : stateTo->makeInstance(m_artboardInstance).release();

        // Fire start events for the state we're changing to.
        if (m_currentState != nullptr)
        {
            m_stateMachineInstance->buildStateKeyFrameBinds(m_currentState);
            fireEvents(StateMachineFireOccurance::atStart,
                       m_currentState->state()->events());
            performListenerActions(StateMachineFireOccurance::atStart,
                                   m_currentState->state()->listenerActions());
        }
        return;
    }

    StateTransition* findRandomTransition(StateInstance* stateFromInstance)
    {
        uint32_t totalWeight = 0;
        auto stateFrom = stateFromInstance->state();
        for (size_t i = 0, length = stateFrom->transitionCount(); i < length;
             i++)
        {
            auto transition = stateFrom->transition(i);
            if (canChangeState(transition->stateTo()))
            {

                auto allowed = transition->allowed(stateFromInstance,
                                                   m_stateMachineInstance,
                                                   this);
                if (allowed == AllowTransition::yes)
                {
                    transition->evaluatedRandomWeight(
                        transition->randomWeight());
                    totalWeight += transition->randomWeight();
                }
                else
                {
                    transition->evaluatedRandomWeight(0);
                    if (allowed == AllowTransition::waitingForExit)
                    {
                        m_waitingForExit = true;
                    }
                }
            }
            else
            {
                transition->evaluatedRandomWeight(0);
            }
        }
        if (totalWeight > 0)
        {
            double randomWeight = randomValue() * totalWeight * 1.0;
            double currentWeight = 0;
            size_t index = 0;
            StateTransition* transition;
            while (index < stateFrom->transitionCount())
            {
                transition = stateFrom->transition(index);
                double transitionWeight =
                    (double)transition->evaluatedRandomWeight();
                if (currentWeight + transitionWeight > randomWeight)
                {
                    transition->useLayerInConditions(m_stateMachineInstance,
                                                     this);
                    return transition;
                }
                currentWeight += transitionWeight;
                index++;
            }
        }
        return nullptr;
    }

    StateTransition* findAllowedTransition(StateInstance* stateFromInstance)
    {
        auto stateFrom = stateFromInstance->state();
        // If it should randomize
        if ((static_cast<LayerStateFlags>(stateFrom->flags()) &
             LayerStateFlags::Random) == LayerStateFlags::Random)
        {
            return findRandomTransition(stateFromInstance);
        }
        // Else search the first valid transition
        for (size_t i = 0, length = stateFrom->transitionCount(); i < length;
             i++)
        {
            auto transition = stateFrom->transition(i);
            if (canChangeState(transition->stateTo()))
            {

                auto allowed = transition->allowed(stateFromInstance,
                                                   m_stateMachineInstance,
                                                   this);
                if (allowed == AllowTransition::yes)
                {
                    transition->evaluatedRandomWeight(
                        transition->randomWeight());
                    transition->useLayerInConditions(m_stateMachineInstance,
                                                     this);
                    return transition;
                }
                else
                {
                    transition->evaluatedRandomWeight(0);
                    if (allowed == AllowTransition::waitingForExit)
                    {
                        m_waitingForExit = true;
                    }
                }
            }
        }
        return nullptr;
    }

    void buildAnimationResetForTransition()
    {
        m_animationReset =
            AnimationResetFactory::fromStates(m_stateFrom,
                                              m_currentState,
                                              m_artboardInstance);
    }

    void clearAnimationReset()
    {
        if (m_animationReset != nullptr)
        {
            AnimationResetFactory::release(std::move(m_animationReset));
            m_animationReset = nullptr;
        }
    }

    bool tryChangeState(StateInstance* stateFromInstance)
    {
        if (stateFromInstance == nullptr)
        {
            return false;
        }
        auto outState = m_currentState;
        auto transition = findAllowedTransition(stateFromInstance);
        if (transition != nullptr)
        {
            clearAnimationReset();
            changeState(transition->stateTo());
            m_stateMachineChangedOnAdvance = true;
#ifdef RIVE_MICROPROFILE
            RiveProfile::instance().recordTransition(
                m_stateMachineInstance->artboard()->name(),
                m_stateMachineInstance->name(),
                m_layer->name(),
                getStateName(outState),
                getStateName(m_currentState),
                m_stateMachineInstance->artboard());
#endif
            // state actually has changed
            m_transition = transition;
            m_transitionDurationProperty =
                m_stateMachineInstance->findTransitionPropertyInstance(
                    transition,
                    StateTransitionBase::durationPropertyKey);
            fireEvents(StateMachineFireOccurance::atStart,
                       transition->events());
            performListenerActions(StateMachineFireOccurance::atStart,
                                   transition->listenerActions());
            if (resolvedDuration() == 0)
            {
                m_transitionCompleted = true;
                fireEvents(StateMachineFireOccurance::atEnd,
                           transition->events());
                performListenerActions(StateMachineFireOccurance::atEnd,
                                       transition->listenerActions());
            }
            else
            {
                m_transitionCompleted = false;
            }

            if (m_stateFrom != m_anyStateInstance)
            {
                // Old state from is done.
                m_stateMachineInstance->removeStateKeyFrameBinds(m_stateFrom);
                delete m_stateFrom;
            }
            m_stateFrom = outState;

            if (!m_transitionCompleted)
            {
                buildAnimationResetForTransition();
            }

            // 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_currentState != nullptr)
            {
                auto advanceTime = 0.0f;
                if (m_stateFrom != nullptr)
                {
                    if (m_stateFrom->state()->is<AnimationState>())
                    {

                        auto instance =
                            static_cast<AnimationStateInstance*>(m_stateFrom)
                                ->animationInstance();

                        advanceTime = instance->spilledTime();
                    }
                }
                m_currentState->advance(advanceTime, m_stateMachineInstance);
            }
            m_mix = 0.0f;
            updateMix(0.0f);
            m_waitingForExit = false;
            return true;
        }
        return false;
    }

    void apply(/*Artboard* artboard*/)
    {
        if (m_animationReset != nullptr)
        {
            m_animationReset->apply(m_artboardInstance);
        }
        if (m_holdAnimation != nullptr)
        {
            m_holdAnimation->apply(m_artboardInstance, m_holdTime, m_mixFrom);
            m_holdAnimation = nullptr;
        }

        KeyFrameInterpolator* interpolator = nullptr;
        if (m_transition != nullptr && m_transition->interpolator() != nullptr)
        {
            interpolator = m_transition->interpolator();
        }

        if (m_stateFrom != nullptr && m_mix < 1.0f)
        {
            auto fromMix = interpolator != nullptr
                               ? interpolator->transform(m_mixFrom)
                               : m_mixFrom;
            m_stateFrom->apply(m_artboardInstance, fromMix);
        }
        if (m_currentState != nullptr)
        {
            auto mix = interpolator != nullptr ? interpolator->transform(m_mix)
                                               : m_mix;
            m_currentState->apply(m_artboardInstance, mix);
        }
    }

    bool stateChangedOnAdvance() const
    {
        return m_stateMachineChangedOnAdvance;
    }

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

private:
    static const int maxIterations = 100;
    StateMachineInstance* m_stateMachineInstance = nullptr;
    const StateMachineLayer* m_layer = nullptr;
    ArtboardInstance* m_artboardInstance = nullptr;

    StateInstance* m_anyStateInstance = nullptr;
    StateInstance* m_currentState = nullptr;
    StateInstance* m_stateFrom = nullptr;

    const StateTransition* m_transition = nullptr;
    BindablePropertyNumber* m_transitionDurationProperty = nullptr;
    std::unique_ptr<AnimationReset> m_animationReset = nullptr;
    bool m_transitionCompleted = false;

    bool m_holdAnimationFrom = false;

    float m_mix = 1.0f;
    float m_mixFrom = 1.0f;
    bool m_stateMachineChangedOnAdvance = 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;
};

/// Representation of a Component from the Artboard Instance and all the
/// listeners it triggers. Allows tracking hover and performing hit detection
/// only once on components that trigger multiple listeners.
class HitDrawable : public HitComponent
{
public:
    HitDrawable(Drawable* drawable,
                Component* component,
                StateMachineInstance* stateMachineInstance,
                bool isOpaque) :
        HitComponent(component, stateMachineInstance)
    {
        this->m_drawable = drawable;
        this->isOpaque = isOpaque;
        if (drawable->isTargetOpaque())
        {
            canEarlyOut = false;
        }
    }
    float hitRadius = 2;
    bool isHovered = false;
    bool canEarlyOut = true;
    bool hasDownListener = false;
    bool hasUpListener = false;
    bool isOpaque = false;
    Drawable* m_drawable;
    std::vector<ListenerGroup*> listeners;

    bool hitTest(Vec2D position) const override { return false; }

    void prepareEvent(Vec2D position,
                      ListenerType hitType,
                      int pointerId) override
    {
        if (canEarlyOut &&
            (hitType != ListenerType::down || !hasDownListener) &&
            (hitType != ListenerType::up || !hasUpListener))
        {
#ifdef TESTING
            earlyOutCount++;
#endif
            return;
        }
        isHovered = hitType != ListenerType::exit && hitTest(position);

        // // iterate all listeners associated with this hit shape
        if (isHovered)
        {
            for (auto listenerGroup : listeners)
            {

                listenerGroup->hover(pointerId);
            }
        }
    }

    HitResult processGamepadInvocation(
        const ListenerInvocation& invocation,
        ScriptedDrawable* alreadyDispatched) override
    {
        return HitResult::none;
    }

    HitResult processEvent(Vec2D position,
                           ListenerType hitType,
                           bool canHit,
                           float timeStamp,
                           int pointerId) override
    {
        // If the shape doesn't have any ListenerType::move / enter / exit and
        // the event being processed is not of the type it needs to handle.
        // There is no need to perform a hitTest (which is relatively expensive
        // and would be happening on every pointer move) so we early out.
        if (canEarlyOut &&
            (hitType != ListenerType::down || !hasDownListener) &&
            (hitType != ListenerType::up || !hasUpListener))
        {
            return HitResult::none;
        }
        bool isBlockingEvent = false;
        // // iterate all listeners associated with this hit shape
        for (auto listenerGroup : listeners)
        {
            if (listenerGroup->isConsumed())
            {
                continue;
            }
            if (listenerGroup->processEvent(m_component,
                                            position,
                                            pointerId,
                                            hitType,
                                            canHit,
                                            timeStamp,
                                            m_stateMachineInstance) ==
                ProcessEventResult::scroll)
            {
                isBlockingEvent = true;
            }
        }
        return (isHovered && canHit)
                   ? (isOpaque || m_drawable->isTargetOpaque() ||
                      isBlockingEvent)
                         ? HitResult::hitOpaque
                         : HitResult::hit
                   : HitResult::none;
    }

    void addListener(ListenerGroup* listenerGroup)
    {
        if (!listenerGroup->canEarlyOut(m_component))
        {
            canEarlyOut = false;
        }
        else
        {
            if (listenerGroup->needsDownListener(m_component))
            {
                hasDownListener = true;
            }
            if (listenerGroup->needsUpListener(m_component))
            {
                hasUpListener = true;
            }
        }
        listeners.push_back(listenerGroup);
    }

    void enablePointerEvents(int pointerId) override
    {
        for (auto listenerGroup : listeners)
        {
            listenerGroup->enable(pointerId);
        }
    }

    void disablePointerEvents(int pointerId) override
    {
        for (auto listenerGroup : listeners)
        {
            listenerGroup->disable(pointerId);
        }
    }
};

/// Representation of a HitDrawable with a Hittable component
class HitExpandable : public HitDrawable
{
public:
    HitExpandable(Drawable* drawable,
                  Component* component,
                  StateMachineInstance* stateMachineInstance,
                  bool isOpaque = false) :
        HitDrawable(drawable, component, stateMachineInstance, isOpaque)
    {}

    bool hitTest(Vec2D position) const override
    {
        return m_component->hitTestPoint(position, true, true);
    }
};

class HitTextRun : public HitExpandable
{
public:
    HitTextRun(Drawable* drawable,
               TextValueRun* component,
               StateMachineInstance* stateMachineInstance,
               bool isOpaque = false) :
        HitExpandable(drawable, component, stateMachineInstance, isOpaque)
    {
        if (component)
        {
            component->isHitTarget(true);
        }
    }
};

class HitLayout : public HitDrawable
{
public:
    HitLayout(Drawable* layout,
              StateMachineInstance* stateMachineInstance,
              bool isOpaque = false) :
        HitDrawable(layout, layout, stateMachineInstance, isOpaque)
    {}

    bool hitTest(Vec2D position) const override
    {
        return m_component->hitTestPoint(position, false, true);
    }
};

class HitNestedArtboard : public HitComponent
{
public:
    HitNestedArtboard(Component* nestedArtboard,
                      StateMachineInstance* stateMachineInstance) :
        HitComponent(nestedArtboard, stateMachineInstance)
    {}
    ~HitNestedArtboard() override {}

    bool hitTest(Vec2D position) const override
    {
        auto nestedArtboard = m_component->as<NestedArtboard>();
        if (nestedArtboard->isCollapsed() || nestedArtboard->isPaused())
        {
            return false;
        }
        Vec2D nestedPosition;
        if (!nestedArtboard->worldToLocal(position, &nestedPosition))
        {
            // Mounted artboard isn't ready or has a 0 scale transform.
            return false;
        }

        for (auto nestedAnimation : nestedArtboard->nestedAnimations())
        {
            if (nestedAnimation->is<NestedStateMachine>())
            {
                auto nestedStateMachine =
                    nestedAnimation->as<NestedStateMachine>();
                if (nestedStateMachine->hitTest(nestedPosition))
                {
                    return true;
                }
            }
        }
        return false;
    }
    HitResult processGamepadInvocation(
        const ListenerInvocation& invocation,
        ScriptedDrawable* alreadyDispatched) override
    {
        auto hitResult = HitResult::none;
        auto nestedArtboard = m_component->as<NestedArtboard>();
        for (auto nestedAnimation : nestedArtboard->nestedAnimations())
        {
            if (nestedAnimation->is<NestedStateMachine>())
            {
                auto nestedStateMachine =
                    nestedAnimation->as<NestedStateMachine>();
                nestedStateMachine->stateMachineInstance()
                    ->broadcastGamepadToScriptedDrawables(invocation,
                                                          alreadyDispatched);
            }
        }
        return hitResult;
    }
    HitResult processEvent(Vec2D position,
                           ListenerType hitType,
                           bool canHit,
                           float timeStamp,
                           int pointerId) override
    {
        auto nestedArtboard = m_component->as<NestedArtboard>();
        HitResult hitResult = HitResult::none;
        if (nestedArtboard->isCollapsed() || nestedArtboard->isPaused())
        {
            return hitResult;
        }
        Vec2D nestedPosition;
        if (!nestedArtboard->worldToLocal(position, &nestedPosition))
        {
            // Mounted artboard isn't ready or has a 0 scale transform.
            return hitResult;
        }

        for (auto nestedAnimation : nestedArtboard->nestedAnimations())
        {
            if (nestedAnimation->is<NestedStateMachine>())
            {
                auto nestedStateMachine =
                    nestedAnimation->as<NestedStateMachine>();
                if (canHit)
                {
                    switch (hitType)
                    {
                        case ListenerType::down:
                            hitResult =
                                nestedStateMachine->pointerDown(nestedPosition,
                                                                pointerId);
                            break;
                        case ListenerType::up:
                            hitResult =
                                nestedStateMachine->pointerUp(nestedPosition,
                                                              pointerId);
                            break;
                        case ListenerType::move:
                            hitResult =
                                nestedStateMachine->pointerMove(nestedPosition,
                                                                timeStamp,
                                                                pointerId);
                            break;
                        case ListenerType::dragStart:
                            nestedStateMachine->dragStart(nestedPosition,
                                                          timeStamp,
                                                          pointerId);
                            break;
                        case ListenerType::dragEnd:
                            nestedStateMachine->dragEnd(nestedPosition,
                                                        timeStamp,
                                                        pointerId);
                            break;
                        case ListenerType::exit:
                            hitResult =
                                nestedStateMachine->pointerExit(nestedPosition,
                                                                pointerId);
                            break;
                        case ListenerType::enter:
                        case ListenerType::event:
                        case ListenerType::click:
                        case ListenerType::componentProvided:
                        case ListenerType::textInput:
                        case ListenerType::viewModel:
                        case ListenerType::drag:
                        case ListenerType::focus:
                        case ListenerType::blur:
                        case ListenerType::keyboard:
                        case ListenerType::semanticAction:
                        case ListenerType::gamepad:
                            break;
                    }
                }
                else
                {
                    switch (hitType)
                    {
                        case ListenerType::down:
                        case ListenerType::up:
                        case ListenerType::move:
                        case ListenerType::exit:
                            nestedStateMachine->pointerExit(nestedPosition,
                                                            pointerId);
                            break;
                        case ListenerType::dragStart:
                        case ListenerType::dragEnd:
                        case ListenerType::enter:
                        case ListenerType::event:
                        case ListenerType::click:
                        case ListenerType::componentProvided:
                        case ListenerType::textInput:
                        case ListenerType::viewModel:
                        case ListenerType::drag:
                        case ListenerType::focus:
                        case ListenerType::blur:
                        case ListenerType::keyboard:
                        case ListenerType::semanticAction:
                        case ListenerType::gamepad:
                            break;
                    }
                }
            }
        }
        return hitResult;
    }
    void prepareEvent(Vec2D position,
                      ListenerType hitType,
                      int pointerId) override
    {}
};

class HitComponentList : public HitComponent
{
public:
    HitComponentList(Component* componentList,
                     StateMachineInstance* stateMachineInstance) :
        HitComponent(componentList, stateMachineInstance)
    {}
    ~HitComponentList() override {}

    bool hitTest(Vec2D position) const override
    {
        auto componentList = m_component->as<ArtboardComponentList>();
        if (componentList->isCollapsed())
        {
            return false;
        }
        const auto& order = componentList->orderedListIndices();
        for (auto it = order.rbegin(); it != order.rend(); ++it)
        {
            const int i = *it;
            Vec2D listPosition;
            if (!componentList->worldToLocal(position, &listPosition, i))
            {
                // Mounted artboard isn't ready or has a 0 scale transform.
                continue;
            }
            auto stateMachine = componentList->stateMachineInstance(i);
            if (stateMachine != nullptr && stateMachine->hitTest(listPosition))
            {
                return true;
            }
        }
        return false;
    }
    HitResult processEvent(Vec2D position,
                           ListenerType hitType,
                           bool canHit,
                           float timeStamp,
                           int pointerId) override
    {
        auto componentList = m_component->as<ArtboardComponentList>();
        HitResult hitResult = HitResult::none;
        bool runningCanHit = canHit;
        if (componentList->isCollapsed())
        {
            return hitResult;
        }
        const auto& order = componentList->orderedListIndices();
        for (auto it = order.rbegin(); it != order.rend(); ++it)
        {
            const int i = *it;
            Vec2D listPosition;
            bool hit = componentList->worldToLocal(position, &listPosition, i);
            if (!hit)
            {
                continue;
            }
            auto stateMachine = componentList->stateMachineInstance(i);
            if (stateMachine != nullptr)
            {
                HitResult itemHitResult = HitResult::none;
                if (runningCanHit)
                {
                    switch (hitType)
                    {
                        case ListenerType::down:
                            itemHitResult =
                                stateMachine->pointerDown(listPosition,
                                                          pointerId);
                            break;
                        case ListenerType::up:
                            itemHitResult =
                                stateMachine->pointerUp(listPosition,
                                                        pointerId);
                            break;
                        case ListenerType::move:
                            itemHitResult =
                                stateMachine->pointerMove(listPosition,
                                                          timeStamp,
                                                          pointerId);
                            break;
                        case ListenerType::exit:
                            itemHitResult =
                                stateMachine->pointerExit(listPosition,
                                                          pointerId);
                            break;
                        case ListenerType::dragStart:
                            stateMachine->dragStart(listPosition,
                                                    0,
                                                    true,
                                                    pointerId);
                            break;
                        case ListenerType::dragEnd:
                            stateMachine->dragEnd(listPosition, 0, pointerId);
                            break;
                        case ListenerType::enter:
                        case ListenerType::event:
                        case ListenerType::click:
                        case ListenerType::componentProvided:
                        case ListenerType::textInput:
                        case ListenerType::viewModel:
                        case ListenerType::drag:
                        case ListenerType::focus:
                        case ListenerType::blur:
                        case ListenerType::keyboard:
                        case ListenerType::semanticAction:
                        case ListenerType::gamepad:
                            break;
                    }
                }
                else
                {
                    switch (hitType)
                    {
                        case ListenerType::down:
                        case ListenerType::up:
                        case ListenerType::move:
                        case ListenerType::exit:
                            stateMachine->pointerExit(listPosition, pointerId);
                            break;
                        case ListenerType::dragStart:
                        case ListenerType::dragEnd:
                        case ListenerType::enter:
                        case ListenerType::event:
                        case ListenerType::click:
                        case ListenerType::componentProvided:
                        case ListenerType::textInput:
                        case ListenerType::viewModel:
                        case ListenerType::drag:
                        case ListenerType::focus:
                        case ListenerType::blur:
                        case ListenerType::keyboard:
                        case ListenerType::semanticAction:
                        case ListenerType::gamepad:
                            break;
                    }
                }
                if ((hitResult == HitResult::none &&
                     (itemHitResult == HitResult::hit ||
                      itemHitResult == HitResult::hitOpaque)) ||
                    (hitResult == HitResult::hit &&
                     itemHitResult == HitResult::hitOpaque))
                {
                    hitResult = itemHitResult;
                }
                if (hitResult == HitResult::hitOpaque)
                {
                    runningCanHit = false;
                }
            }
        }
        return hitResult;
    }
    HitResult processGamepadInvocation(
        const ListenerInvocation& invocation,
        ScriptedDrawable* alreadyDispatched) override
    {
        auto componentList = m_component->as<ArtboardComponentList>();
        HitResult hitResult = HitResult::none;
        bool runningCanHit = true;
        if (componentList->isCollapsed())
        {
            return hitResult;
        }
        const auto& order = componentList->orderedListIndices();
        for (auto it = order.rbegin(); it != order.rend(); ++it)
        {
            const int i = *it;
            auto stateMachine = componentList->stateMachineInstance(i);
            if (stateMachine != nullptr)
            {
                HitResult itemHitResult = HitResult::none;
                if (runningCanHit)
                {
                    itemHitResult =
                        stateMachine->broadcastGamepadToScriptedDrawables(
                            invocation,
                            alreadyDispatched);
                }

                if ((hitResult == HitResult::none &&
                     (itemHitResult == HitResult::hit ||
                      itemHitResult == HitResult::hitOpaque)) ||
                    (hitResult == HitResult::hit &&
                     itemHitResult == HitResult::hitOpaque))
                {
                    hitResult = itemHitResult;
                }
                if (hitResult == HitResult::hitOpaque)
                {
                    runningCanHit = false;
                }
            }
        }
        return hitResult;
    }
    void prepareEvent(Vec2D position,
                      ListenerType hitType,
                      int pointerId) override
    {}
};

class ListenerViewModel;

// Helper that holds one view model property reference, listens to its dirt,
// and reports the parent ListenerViewModel when the property changes.
class ListenerViewModelPropertyBinding : public ViewModelValueDependent
{
public:
    ListenerViewModelPropertyBinding(ListenerViewModel* parent,
                                     ViewModelInstanceValue* vmProp);
    virtual ~ListenerViewModelPropertyBinding();
    void addDirt(ComponentDirt value, bool recurse) override;
    void relinkDataBind() override;
    ViewModelInstanceValue* value() { return m_viewModelInstanceValue.get(); }

protected:
    ListenerViewModel* m_parent = nullptr;
    rive::rcp<ViewModelInstanceValue> m_viewModelInstanceValue = nullptr;
    void clearDataContext();
};
class ListenerViewModelPropertyBindingListener
    : public ListenerViewModelPropertyBinding
{
public:
    ListenerViewModelPropertyBindingListener(
        ListenerViewModel* parent,
        ViewModelInstanceValue* vmProp,
        const StateMachineListenerSingle* listener);
    void relinkDataBind() override;

private:
    const StateMachineListenerSingle* m_listener;
};
class ListenerViewModelPropertyBindingInput
    : public ListenerViewModelPropertyBinding
{
public:
    ListenerViewModelPropertyBindingInput(
        ListenerViewModel* parent,
        ViewModelInstanceValue* vmProp,
        const ListenerInputTypeViewModel* listenerInput);
    void relinkDataBind() override;

private:
    const ListenerInputTypeViewModel* m_listenerInput;
};

class ListenerViewModel
{
public:
    virtual ~ListenerViewModel();
    ListenerViewModel(StateMachineInstance* smInstance,
                      const StateMachineListener* listener) :
        m_stateMachineInstance(smInstance), m_listener(listener)
    {}

    void clearDataContext() { m_propertyBindings.clear(); }
    void bindFromContext(rcp<DataContext> dataContext)
    {
        m_dataContext = dataContext;
        clearDataContext();
        if (m_listener->is<StateMachineListenerSingle>())
        {
            auto vmProp = dataContext->getViewModelProperty(
                m_listener->as<StateMachineListenerSingle>()->dataBindPath());
            if (vmProp != nullptr)
            {
                m_propertyBindings.push_back(
                    std::make_unique<ListenerViewModelPropertyBindingListener>(
                        this,
                        vmProp,
                        m_listener->as<StateMachineListenerSingle>()));
            }
        }
        else
        {
            size_t index = 0;
            while (index < m_listener->listenerInputTypeCount())
            {
                auto listenerInputType = m_listener->listenerInputType(index);
                if (listenerInputType->is<ListenerInputTypeViewModel>())
                {
                    auto listenerInputTypeVM =
                        listenerInputType->as<ListenerInputTypeViewModel>();
                    auto vmProp = dataContext->getViewModelProperty(
                        listenerInputTypeVM->dataBindPath());
                    if (vmProp != nullptr)
                    {
                        m_propertyBindings.push_back(
                            std::make_unique<
                                ListenerViewModelPropertyBindingInput>(
                                this,
                                vmProp,
                                listenerInputTypeVM));
                    }
                }
                index++;
            }
        }
        // A trigger fired before this bind (e.g. during script init) stays
        // pending until the frame resets it; report it so it isn't lost.
        for (auto& binding : m_propertyBindings)
        {
            auto value = binding->value();
            if (value != nullptr && value->is<ViewModelInstanceTrigger>() &&
                value->as<ViewModelInstanceTrigger>()->propertyValue() != 0)
            {
                reportToStateMachine(value);
            }
        }
    }
    void reportToStateMachine(ViewModelInstanceValue* value)
    {
        if (!value->is<ViewModelInstanceTrigger>() ||
            value->as<ViewModelInstanceTrigger>()->propertyValue() != 0)
        {
            m_stateMachineInstance->reportListenerViewModel(this);
        }
    }
    const StateMachineListener* listener() { return m_listener; }
    DataContext* dataContext()
    {
        if (m_dataContext)
        {

            return m_dataContext.get();
        }
        return nullptr;
    }

private:
    StateMachineInstance* m_stateMachineInstance = nullptr;
    const StateMachineListener* m_listener = nullptr;
    rcp<DataContext> m_dataContext = nullptr;
    std::vector<std::unique_ptr<ListenerViewModelPropertyBinding>>
        m_propertyBindings;
};

ListenerViewModelPropertyBinding::ListenerViewModelPropertyBinding(
    ListenerViewModel* parent,
    ViewModelInstanceValue* vmProp) :
    m_parent(parent), m_viewModelInstanceValue(rive::ref_rcp(vmProp))
{
    vmProp->addDependent(this);
}

void ListenerViewModelPropertyBinding::relinkDataBind() {}

ListenerViewModelPropertyBinding::~ListenerViewModelPropertyBinding()
{
    clearDataContext();
}

void ListenerViewModelPropertyBinding::clearDataContext()
{

    if (m_viewModelInstanceValue != nullptr)
    {
        m_viewModelInstanceValue->removeDependent(this);
        m_viewModelInstanceValue = nullptr;
    }
}

ListenerViewModelPropertyBindingListener::
    ListenerViewModelPropertyBindingListener(
        ListenerViewModel* parent,
        ViewModelInstanceValue* vmProp,
        const StateMachineListenerSingle* listener) :
    ListenerViewModelPropertyBinding(parent, vmProp), m_listener(listener)
{}

void ListenerViewModelPropertyBindingListener::relinkDataBind()
{
    auto dataContext = m_parent->dataContext();
    if (dataContext)
    {

        auto vmProp =
            dataContext->getViewModelProperty(m_listener->dataBindPath());
        if (vmProp != m_viewModelInstanceValue.get())
        {
            clearDataContext();
            if (vmProp != nullptr)
            {
                m_viewModelInstanceValue = ref_rcp(vmProp);
                vmProp->addDependent(this);
            }
        }
    }
}

ListenerViewModelPropertyBindingInput::ListenerViewModelPropertyBindingInput(
    ListenerViewModel* parent,
    ViewModelInstanceValue* vmProp,
    const ListenerInputTypeViewModel* listenerInput) :
    ListenerViewModelPropertyBinding(parent, vmProp),
    m_listenerInput(listenerInput)
{}

void ListenerViewModelPropertyBindingInput::relinkDataBind()
{
    auto dataContext = m_parent->dataContext();
    if (dataContext)
    {
        auto vmProp =
            dataContext->getViewModelProperty(m_listenerInput->dataBindPath());
        if (vmProp != m_viewModelInstanceValue.get())
        {
            clearDataContext();
            if (vmProp != nullptr)
            {
                m_viewModelInstanceValue = ref_rcp(vmProp);
                vmProp->addDependent(this);
            }
        }
    }
}

void ListenerViewModelPropertyBinding::addDirt(ComponentDirt value,
                                               bool recurse)
{
    if (m_parent != nullptr && m_viewModelInstanceValue != nullptr)
    {
        m_parent->reportToStateMachine(m_viewModelInstanceValue.get());
    }
}

ListenerViewModel::~ListenerViewModel() { clearDataContext(); }

} // namespace rive

HitResult StateMachineInstance::updateListeners(Vec2D position,
                                                ListenerType hitType,
                                                int pointerId,
                                                float timeStamp)
{
    if (m_artboardInstance->frameOrigin())
    {
        position -= Vec2D(
            m_artboardInstance->originX() * m_artboardInstance->layoutWidth(),
            m_artboardInstance->originY() * m_artboardInstance->layoutHeight());
    }
    // Invert the artboard's own rotation/scale (applied in drawInternal after
    // the frame-origin translation) so listener hit-testing maps into content
    // space. Mirrors the adjustment in hitTest(Vec2D).
    if (m_artboardInstance->hasSelfTransform())
    {
        Mat2D inverse;
        if (m_artboardInstance->selfTransform().invert(&inverse))
        {
            position = inverse * position;
        }
    }
    // First reset all listener groups before processing the events
    for (const auto& listenerGroup : m_listenerGroups)
    {
        listenerGroup.get()->reset(pointerId);
    }
    // Next prepare the event to set the common hover status for each group
    for (const auto& hitShape : m_hitComponents)
    {
        hitShape->prepareEvent(position, hitType, pointerId);
    }
    bool hitSomething = false;
    bool hitOpaque = false;
    // Process the events
    for (const auto& hitShape : m_hitComponents)
    {
        HitResult hitResult = hitShape->processEvent(position,
                                                     hitType,
                                                     !hitOpaque,
                                                     timeStamp,
                                                     pointerId);
        if (hitResult != HitResult::none)
        {
            hitSomething = true;
            if (hitResult == HitResult::hitOpaque)
            {
                hitOpaque = true;
            }
        }
    }
    // Finally release events that are complete
    if (hitType == ListenerType::exit)
    {
        for (const auto& listenerGroup : m_listenerGroups)
        {
            listenerGroup.get()->releaseEvent(pointerId);
        }
    }

    return hitSomething ? hitOpaque ? HitResult::hitOpaque : HitResult::hit
                        : HitResult::none;
}

bool StateMachineInstance::hitTest(Vec2D position) const
{
    if (m_artboardInstance->frameOrigin())
    {
        position -= Vec2D(
            m_artboardInstance->originX() * m_artboardInstance->layoutWidth(),
            m_artboardInstance->originY() * m_artboardInstance->layoutHeight());
    }
    // Invert the artboard's own rotation/scale (applied in drawInternal after
    // the frame-origin translation) so the pointer maps into content space.
    // Covers nested state machines too, which funnel through here.
    if (m_artboardInstance->hasSelfTransform())
    {
        Mat2D inverse;
        if (m_artboardInstance->selfTransform().invert(&inverse))
        {
            position = inverse * position;
        }
    }

    for (const auto& hitShape : m_hitComponents)
    {
        // TODO: quick reject.

        if (hitShape->hitTest(position))
        {
            return true;
        }
    }
    return false;
}

HitResult StateMachineInstance::pointerMove(Vec2D position,
                                            float timeStamp,
                                            int id)
{
    return updateListeners(position, ListenerType::move, id, timeStamp);
}
HitResult StateMachineInstance::pointerDown(Vec2D position, int id)
{
    return updateListeners(position, ListenerType::down, id);
}
HitResult StateMachineInstance::pointerUp(Vec2D position, int id)
{
    return updateListeners(position, ListenerType::up, id);
}
HitResult StateMachineInstance::pointerExit(Vec2D position, int id)
{
    return updateListeners(position, ListenerType::exit, id);
}
HitResult StateMachineInstance::dragStart(Vec2D position,
                                          float timeStamp,
                                          bool disablePointer,
                                          int pointerId)
{
    if (disablePointer)
    {
        disablePointerEvents(pointerId);
    }
    auto hit = updateListeners(position, ListenerType::dragStart, pointerId);
    return hit;
}
HitResult StateMachineInstance::dragEnd(Vec2D position,
                                        float timeStamp,
                                        int pointerId)
{
    enablePointerEvents(pointerId);
    auto hit = updateListeners(position, ListenerType::dragEnd, pointerId);
    pointerMove(position, timeStamp, pointerId);
    return hit;
}

#ifdef TESTING
const LayerState* StateMachineInstance::layerState(size_t index)
{
    if (index < m_machine->layerCount())
    {
        return m_layers[index].currentState();
    }
    return nullptr;
}
#endif

void StateMachineInstance::addToHitLookup(
    Component* target,
    bool isLayoutComponent,
    std::unordered_map<Component*, HitDrawable*>& hitLookup,
    ListenerGroup* listenerGroup,
    bool isOpaque)
{
    // target could either be a LayoutComponent or a DrawableProxy
    if (isLayoutComponent)
    {
        HitLayout* hitLayout;
        auto itr = hitLookup.find(target);
        if (itr == hitLookup.end())
        {
            auto hs = std::make_unique<HitLayout>(target->as<Drawable>(),
                                                  this,
                                                  isOpaque);
            hitLookup[target] = hitLayout = hs.get();
            m_hitComponents.push_back(std::move(hs));
        }
        else
        {
            hitLayout = static_cast<HitLayout*>(itr->second);
        }
        hitLayout->addListener(listenerGroup);
        if (isOpaque)
        {
            hitLayout->isOpaque = true;
        }
        return;
    }

    if (target->is<Shape>())
    {
        HitExpandable* hitShape;
        auto itr = hitLookup.find(target);
        if (itr == hitLookup.end())
        {
            Shape* shape = target->as<Shape>();
            shape->addFlags(PathFlags::neverDeferUpdate);
            shape->addDirt(ComponentDirt::Path, true);
            auto hs = std::make_unique<HitExpandable>(shape, shape, this);
            hitLookup[target] = hitShape = hs.get();
            m_hitComponents.push_back(std::move(hs));
        }
        else
        {
            hitShape = static_cast<HitExpandable*>(itr->second);
        }
        hitShape->addListener(listenerGroup);
        return;
    }

    if (target->is<TextValueRun>())
    {
        HitTextRun* hitTextRun;
        auto itr = hitLookup.find(target);
        if (itr == hitLookup.end())
        {
            TextValueRun* run = target->as<TextValueRun>();
            run->textComponent()->addDirt(ComponentDirt::Path, true);
            auto hs =
                std::make_unique<HitTextRun>(run->textComponent(), run, this);
            hitLookup[target] = hitTextRun = hs.get();
            m_hitComponents.push_back(std::move(hs));
        }
        else
        {
            hitTextRun = static_cast<HitTextRun*>(itr->second);
        }
        hitTextRun->addListener(listenerGroup);
        return;
    }

    if (target->is<ContainerComponent>())
    {
        target->as<ContainerComponent>()->forEachChild([&](Component* child) {
            addToHitLookup(child,
                           child->is<LayoutComponent>(),
                           hitLookup,
                           listenerGroup,
                           isOpaque);
            return false;
        });
        return;
    }
}

StateMachineInstance::StateMachineInstance(const StateMachine* machine,
                                           ArtboardInstance* instance) :
    Scene(instance), m_machine(machine)
{
    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;
        }
#ifdef WITH_RIVE_TOOLS
        auto instance = m_inputInstances[i];
        if (instance != nullptr)
        {
            instance->m_index = i;
        }
#endif
    }

    m_layerCount = machine->layerCount();
    m_layers = new StateMachineLayerInstance[m_layerCount];
    for (size_t i = 0; i < m_layerCount; i++)
    {
        m_layers[i].init(this, machine->layer(i), m_artboardInstance);
    }

    // Initialize dataBinds. All databinds are cloned for the state machine
    // instance. That enables binding each instance to its own context without
    // polluting the rest.
    auto dataBindCount = machine->dataBindCount();
    for (size_t i = 0; i < dataBindCount; i++)
    {
        auto dataBind = machine->dataBind(i);
        if (!dataBind->target())
        {
            continue;
        }
        auto dataBindClone = static_cast<DataBind*>(dataBind->clone());
        dataBindClone->file(dataBind->file());
        if (dataBind->converter() != nullptr)
        {
            dataBindClone->converter(
                dataBind->converter()->clone()->as<DataConverter>());
        }
        addDataBind(dataBindClone);
        if (dataBind->target()->is<BindableProperty>())
        {
            auto bindableProperty = dataBind->target()->as<BindableProperty>();
            auto bindablePropertyInstance =
                m_bindablePropertyInstances.find(bindableProperty);
            BindableProperty* bindablePropertyClone;
            if (bindablePropertyInstance == m_bindablePropertyInstances.end())
            {
                bindablePropertyClone =
                    bindableProperty->clone()->as<BindableProperty>();
                m_bindablePropertyInstances[bindableProperty] =
                    bindablePropertyClone;
            }
            else
            {
                bindablePropertyClone = bindablePropertyInstance->second;
            }
            dataBindClone->target(bindablePropertyClone);
            // We are only storing in this unordered map data binds that are
            // targetting the source. For now, this is only the case for
            // listener actions.
            if ((static_cast<DataBindFlags>(dataBindClone->flags()) &
                 DataBindFlags::ToSource) == DataBindFlags::ToSource)
            {
                m_bindableDataBindsToSource[bindablePropertyClone] =
                    dataBindClone;
            }
            else
            {
                m_bindableDataBindsToTarget[bindablePropertyClone] =
                    dataBindClone;
            }
        }
        else
        {
            auto* originalTarget = dataBind->target();
            dataBindClone->target(originalTarget);
            if (originalTarget->is<StateTransitionBase>())
            {
                // Create a per-instance BindablePropertyNumber to
                // receive the data-bound value instead of writing
                // to the shared StateTransition. Swap the target
                // and propertyKey so the normal apply() path writes
                // to our instance-local property.
                auto* prop = new BindablePropertyNumber();
                m_transitionPropertyInstances[originalTarget]
                                             [dataBind->propertyKey()] = prop;
                dataBindClone->target(prop);
                dataBindClone->propertyKey(
                    BindablePropertyNumberBase::propertyValuePropertyKey);
            }
        }
    }

    // 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<Component*, HitDrawable*> hitLookup;
    for (std::size_t i = 0; i < machine->listenerCount(); i++)
    {
        auto listener = machine->listener(i);
        if (listener->hasListener(ListenerType::event))
        {
            continue;
        }
        if (listener->hasListener(ListenerType::viewModel))
        {
            auto vmListener = new ListenerViewModel(this, listener);
            m_listenerViewModels.push_back(vmListener);
            continue;
        }
        // Handle focus/blur listeners - they're driven by FocusManager,
        // not pointer events.
        if (listener->hasListener(ListenerType::focus) ||
            listener->hasListener(ListenerType::blur))
        {
            auto target = m_artboardInstance->resolve(listener->targetId());
            if (target != nullptr && target->is<Node>())
            {
                auto node = target->as<Node>();
                // Find FocusData child of the node
                FocusData* focusData = nullptr;
                for (auto child : node->children())
                {
                    if (child->is<FocusData>())
                    {
                        focusData = child->as<FocusData>();
                        break;
                    }
                }
                if (focusData != nullptr)
                {
                    auto focusGroup =
                        std::make_unique<FocusListenerGroup>(focusData,
                                                             listener,
                                                             this);
                    m_focusListenerGroups.push_back(std::move(focusGroup));
                }
            }
        }
        if (listener->hasListener(ListenerType::keyboard) ||
            listener->hasListener(ListenerType::textInput))
        {
            auto target = m_artboardInstance->resolve(listener->targetId());
            if (target != nullptr && target->is<Node>())
            {
                auto node = target->as<Node>();
                // Find FocusData child of the node
                FocusData* focusData = nullptr;
                for (auto child : node->children())
                {
                    if (child->is<FocusData>())
                    {
                        focusData = child->as<FocusData>();
                        break;
                    }
                }
                if (focusData != nullptr)
                {
                    auto keyboardGroup =
                        std::make_unique<KeyboardListenerGroup>(focusData,
                                                                listener,
                                                                this);
                    m_keyboardListenerGroups.push_back(
                        std::move(keyboardGroup));
                }
            }
        }
        // Semantic listeners are driven by accessibility actions rather
        // than pointer events. The editor enforces that the listener's
        // target Node owns a SemanticData child directly; no ancestor
        // walk is performed here.
        if (listener->hasListener(ListenerType::semanticAction))
        {
            auto target = m_artboardInstance->resolve(listener->targetId());
            if (target != nullptr && target->is<Node>())
            {
                for (auto* child : target->as<Node>()->children())
                {
                    if (child->is<SemanticData>())
                    {
                        m_semanticListenerGroups.push_back(
                            std::make_unique<SemanticListenerGroup>(
                                child->as<SemanticData>(),
                                listener,
                                this));
                        break;
                    }
                }
            }
        }

        if (listener->hasListeners(kPointerHitListenerTypes))
        {
            auto listenerGroup = std::make_unique<ListenerGroup>(listener);
            auto target = m_artboardInstance->resolve(listener->targetId());
            if (target != nullptr && target->is<Component>())
            {
                bool isLayoutComponent = false;
                if (target->is<LayoutComponent>())
                {
                    isLayoutComponent = true;
                    target = target->as<LayoutComponent>()->proxy();
                }
                addToHitLookup(target->as<Component>(),
                               isLayoutComponent,
                               hitLookup,
                               listenerGroup.get(),
                               false);
            }
            m_listenerGroups.push_back(std::move(listenerGroup));
        }
        if (listener->hasListener(ListenerType::gamepad))
        {
            auto target = m_artboardInstance->resolve(listener->targetId());
            auto node = target->as<Node>();
            FocusData* focusData = nullptr;
            for (auto child : node->children())
            {
                if (child->is<FocusData>())
                {
                    focusData = child->as<FocusData>();
                    break;
                }
            }
            if (focusData != nullptr)
            {
                auto gamepadGroup =
                    std::make_unique<GamepadListenerGroup>(focusData,
                                                           listener,
                                                           this);
                m_gamepadListenerGroups.push_back(std::move(gamepadGroup));
            }
        }
    }

    std::vector<ListenerGroupProvider*> componentProvidedListenerGroups;
    for (auto core : m_artboardInstance->objects())
    {
        if (core == nullptr)
        {
            continue;
        }
        auto provider = ListenerGroupProvider::from(core);
        if (provider != nullptr)
        {
            componentProvidedListenerGroups.push_back(provider);
        }
    }
    for (auto component : componentProvidedListenerGroups)
    {
        auto groupsWithTargets = component->listenerGroups();
        for (auto groupWithTargets : groupsWithTargets)
        {
            auto group = groupWithTargets->group();
            auto targets = groupWithTargets->targets();
            for (auto target : targets)
            {
                auto component = target->component();
                bool isLayoutComponent = component->is<LayoutComponent>() ||
                                         (component->is<Drawable>() &&
                                          component->as<Drawable>()->isProxy());
                addToHitLookup(target->component(),
                               isLayoutComponent,
                               hitLookup,
                               group,
                               target->isOpaque());
            }
            m_listenerGroups.push_back(std::unique_ptr<ListenerGroup>(group));
            for (auto target : targets)
            {
                delete target;
            }
            delete groupWithTargets;
        }
        auto hitComponents = component->hitComponents(this);
        for (auto* hitComponent : hitComponents)
        {
            m_hitComponents.push_back(
                std::unique_ptr<HitComponent>(hitComponent));
        }
    }

    for (auto nestedArtboard : instance->nestedArtboards())
    {
        // TODO: @hernan as an optimization only create a HitNestedArtboard if
        // the nested artboard has state machines or if it is bound via data
        // binding
        auto hn =
            std::make_unique<HitNestedArtboard>(nestedArtboard->as<Component>(),
                                                this);
        m_hitComponents.push_back(std::move(hn));
        for (auto animation : nestedArtboard->nestedAnimations())
        {
            if (animation->is<NestedStateMachine>())
            {
                if (auto notifier = animation->as<NestedStateMachine>()
                                        ->stateMachineInstance())
                {
                    notifier->setNestedArtboard(nestedArtboard);
                    notifier->addNestedEventListener(this);
                }
            }
            else if (animation->is<NestedLinearAnimation>())
            {
                if (auto notifier = animation->as<NestedLinearAnimation>()
                                        ->animationInstance())
                {
                    notifier->setNestedArtboard(nestedArtboard);
                    notifier->addNestedEventListener(this);
                }
            }
        }
    }
    for (auto componentList : instance->artboardComponentLists())
    {
        auto hc =
            std::make_unique<HitComponentList>(componentList->as<Component>(),
                                               this);
        m_hitComponents.push_back(std::move(hc));
    }

#ifdef WITH_RIVE_TEXT
    // Register TextInputs as hit targets for drag-to-select functionality
    for (auto textInput : instance->objects<TextInput>())
    {
        auto textInputGroup =
            std::make_unique<TextInputListenerGroup>(textInput, this);
        auto hitExpandable = std::make_unique<HitExpandable>(
            textInput->as<Drawable>(),
            textInput->as<Component>(),
            this,
            true); // isOpaque - TextInput blocks hits behind it
        hitExpandable->addListener(textInputGroup.get());
        m_hitComponents.push_back(std::move(hitExpandable));
        m_listenerGroups.push_back(std::move(textInputGroup));
    }
#endif

    // Initialize local instances of ScriptedObjects
    for (auto& scriptedOb : machine->scriptedObjects())
    {
        m_scriptedObjectsMap[scriptedOb] =
            scriptedOb->cloneScriptedObject(this);
    }
    for (auto& scriptedPair : m_scriptedObjectsMap)
    {
        scriptedPair.second->dataContext(m_artboardInstance->dataContext());
    }
    initScriptedObjects();
    // Register Scripted objects as keyboard and text targets when expected,
    // and collect every scripted drawable that wants gamepad events so we can
    // broadcast to it later regardless of focus.
    for (auto object : instance->objects<ContainerComponent>())
    {
        auto scriptedObject = ScriptedObject::from(object);
        if (!scriptedObject)
        {
            continue;
        }
        if (scriptedObject->wantsKeyboardInput() ||
            scriptedObject->wantsTextInput())
        {
            for (auto& child : object->as<ContainerComponent>()->children())
            {
                if (child->is<FocusData>())
                {

                    auto keyboardGroup =
                        std::make_unique<KeyboardListenerGroup>(
                            child->as<FocusData>(),
                            nullptr,
                            this);
                    m_keyboardListenerGroups.push_back(
                        std::move(keyboardGroup));
                    break;
                }
            }
        }
        if ((scriptedObject->wantsGamePadConnect() ||
             scriptedObject->wantsGamePadDisconnect() ||
             scriptedObject->wantsGamePadEvent()) &&
            object->is<ScriptedDrawable>())
        {
            m_gamepadScriptedDrawables.push_back(
                object->as<ScriptedDrawable>());
        }
    }
    sortHitComponents();

    // Build the focus tree for this artboard. focusManager() returns the
    // external manager if set (e.g., when Dart owns the manager at edit time),
    // otherwise the internal one. For nested artboards that need a parent
    // FocusNode, Dart should call buildFocusTreeWithParent() after init.
    m_artboardInstance->buildFocusTree(focusManager(), nullptr);
}

ScriptedObject* StateMachineInstance::scriptedObject(
    const ScriptedObject* source) const
{
    auto itr = m_scriptedObjectsMap.find(source);
    if (itr != m_scriptedObjectsMap.end())
    {
        return itr->second;
    }
    return nullptr;
}

StateMachineInstance::~StateMachineInstance()
{
    // Clean up focus tree BEFORE the internal FocusManager is destroyed.
    // The artboard stores a raw pointer to our m_focusManager, so we must
    // clear it before m_focusManager's implicit destruction at end of dtor.
    if (m_externalFocusManager == nullptr && m_artboardInstance != nullptr)
    {
        m_artboardInstance->cleanupFocusTree();
    }

    // Clean up semantic tree BEFORE the internal SemanticManager is destroyed.
    // Only needed when we own the manager; if external, the parent cleans up.
    if (m_externalSemanticManager == nullptr && m_semanticManager != nullptr &&
        m_artboardInstance != nullptr)
    {
        m_artboardInstance->cleanupSemanticTree();
    }
    m_embedderGamepads.clear();

    unbind();
    for (auto inst : m_inputInstances)
    {
        delete inst;
    }
    for (auto& listenerGroup : m_listenerGroups)
    {
        listenerGroup.reset();
    }
    deleteDataBinds();
    // The keyframe-value binds were just deleted by deleteDataBinds(); drop the
    // now-stale tracking pointers before the layers (and their LAIs/holders)
    // are destroyed below.
    m_stateKeyFrameDataBinds.clear();
    delete[] m_layers;
    for (auto pair : m_bindablePropertyInstances)
    {
        delete pair.second;
        pair.second = nullptr;
    }
    for (auto& outer : m_transitionPropertyInstances)
    {
        for (auto& inner : outer.second)
        {
            delete inner.second;
        }
    }
    m_transitionPropertyInstances.clear();
    for (auto& listenerViewModel : m_listenerViewModels)
    {
        delete listenerViewModel;
    }
    m_bindablePropertyInstances.clear();
    for (auto& pair : m_scriptedObjectsMap)
    {
        delete pair.second;
        pair.second = nullptr;
    }
    m_scriptedObjectsMap.clear();
}

// When a state machine instanced by a higher level runtime is destroyed, we
// need to clean up all its references from the nested artboard children. The
// reason is that the artboard might still be kept alive and it might have
// invalid pointers. This is not necessary for nested state machines because
// they are destroyed altogether.
void StateMachineInstance::dispose() { removeEventListeners(); }

void StateMachineInstance::removeEventListeners()
{
    if (m_artboardInstance != nullptr)
    {
        for (auto nestedArtboard : m_artboardInstance->nestedArtboards())
        {
            if (nestedArtboard == nullptr)
            {
                continue;
            }
            for (auto animation : nestedArtboard->nestedAnimations())
            {
                if (animation == nullptr)
                {
                    continue;
                }
                if (animation->is<NestedStateMachine>())
                {
                    if (auto notifier = animation->as<NestedStateMachine>()
                                            ->stateMachineInstance())
                    {
                        notifier->removeNestedEventListener(this);
                    }
                }
                else if (animation->is<NestedLinearAnimation>())
                {
                    if (auto notifier = animation->as<NestedLinearAnimation>()
                                            ->animationInstance())
                    {
                        notifier->removeNestedEventListener(this);
                    }
                }
            }
        }
    }
}

#ifdef WITH_RIVE_TOOLS
void StateMachineInstance::onDataBindChanged(DataBindChanged callback)
{
    for (auto databind : m_dataBinds)
    {
        databind->onChanged(callback);
    }
}
#endif

void StateMachineInstance::sortHitComponents()
{
    auto hitShapesCount = m_hitComponents.size();
    auto currentSortedIndex = 0;
    auto count = 0;
    // Since the Artboard is not a drawable, we move all hit components
    // pointing to the artboard to the front of the list
    for (auto& comp : m_hitComponents)
    {
        if (comp->component() != nullptr && comp->component()->is<Artboard>())
        {
            if (currentSortedIndex != count)
            {

                std::iter_swap(m_hitComponents.begin() + currentSortedIndex,
                               m_hitComponents.begin() + count);
            }
            currentSortedIndex++;
        }
        count++;
    }
    Drawable* last = m_artboardInstance->firstDrawable();
    if (last)
    {
        // walk to the end, so we can visit in reverse-order
        while (last->prev)
        {
            last = last->prev;
        }
    }
    for (auto drawable = last; drawable; drawable = drawable->next)
    {
        for (size_t i = currentSortedIndex; i < hitShapesCount; i++)
        {
            if (m_hitComponents[i]->component() == drawable)
            {
                if (currentSortedIndex != i)
                {
                    std::iter_swap(m_hitComponents.begin() + currentSortedIndex,
                                   m_hitComponents.begin() + i);
                }
                currentSortedIndex++;
            }
        }
        if (currentSortedIndex == hitShapesCount)
        {
            break;
        }
    }
}

bool StateMachineInstance::tryChangeState()
{
    updateDataBinds(false);
    bool hasChangedState = false;
    for (size_t i = 0; i < m_layerCount; i++)
    {
        if (m_layers[i].updateState())
        {
            hasChangedState = true;
        }
    }
    return hasChangedState;
}

void StateMachineInstance::applyEvents()
{
    m_eventsAppliedDuringLoop.clear();
    int maxIterations = 100;
    int currentIteration = 0;
    while ((m_reportedEvents.size() > 0 ||
            m_reportedListenerViewModels.size() > 0) &&
           currentIteration++ < maxIterations)
    {
        updateDataBinds(false);
        m_reportingEvents = m_reportedEvents;
        m_reportingListenerViewModels = m_reportedListenerViewModels;
        m_reportedEvents.clear();
        m_reportedListenerViewModels.clear();
        if (currentIteration > 1)
        {
            // These were reported during the loop, so no host has seen them
            // yet; keep them visible until the next applyEvents.
            m_eventsAppliedDuringLoop.insert(m_eventsAppliedDuringLoop.end(),
                                             m_reportingEvents.begin(),
                                             m_reportingEvents.end());
        }
        this->notifyEventListeners(m_reportingEvents, nullptr);
        this->notifyListenerViewModels(m_reportingListenerViewModels);
    }
    if (currentIteration >= maxIterations)
    {
        fprintf(stderr,
                "%s StateMachine exceeded max event iterations"
                "on artboard %s\n",
                stateMachine()->name().c_str(),
                artboard()->name().c_str());
    }
}

void StateMachineInstance::setExternalFocusManager(FocusManager* manager)
{
    if (m_externalFocusManager == manager)
    {
        return;
    }

    // Clean up old focus tree if one was built
    if (m_artboardInstance != nullptr &&
        m_artboardInstance->focusManager() != nullptr)
    {
        m_artboardInstance->cleanupFocusTree();
    }

    m_externalFocusManager = manager;

    // Rebuild focus tree with new manager (focusManager() will return the new
    // external manager if set, or internal if null)
    if (m_artboardInstance != nullptr)
    {
        m_artboardInstance->buildFocusTree(focusManager(), nullptr);
    }
}

void StateMachineInstance::enableSemantics()
{
    if (semanticManager() != nullptr)
    {
        return;
    }
    m_semanticManager = std::make_unique<SemanticManager>();
    if (m_artboardInstance != nullptr)
    {
        m_artboardInstance->buildSemanticTree(semanticManager(), nullptr);
    }
}

void StateMachineInstance::setExternalSemanticManager(
    SemanticManager* manager,
    rcp<SemanticNode> parentNode)
{
    if (m_externalSemanticManager == manager)
    {
        return;
    }

    // Clean up the old semantic tree if one was built with a different manager.
    if (m_artboardInstance != nullptr &&
        m_artboardInstance->semanticManager() != nullptr)
    {
        m_artboardInstance->cleanupSemanticTree();
    }

    m_externalSemanticManager = manager;

    // Rebuild with the new manager. semanticManager() now returns the external
    // manager if set, or the internal one if null.
    if (m_artboardInstance != nullptr)
    {
        m_artboardInstance->buildSemanticTree(semanticManager(), parentNode);
    }
}

void StateMachineInstance::queueFocusEvent(FocusListenerGroup* group,
                                           bool isFocus)
{
    m_queuedFocusEvents.push_back({group, isFocus});
    m_needsAdvance = true;
}

void StateMachineInstance::setFocus(FocusData* focusData)
{
    if (focusData != nullptr)
    {
        auto node = focusData->focusNode();
        auto* fm = focusManager();
        fm->setFocus(node);
    }
    else
    {
        focusManager()->clearFocus();
    }
}

StateMachineInstance::FocusState StateMachineInstance::focusState() const
{
    FocusState state;
    const FocusManager* fm =
        m_externalFocusManager ? m_externalFocusManager : &m_focusManager;
    // primaryFocusPtr() avoids a refcount bump on this poll-friendly path.
    FocusNode* focus = fm->primaryFocusPtr();
    if (focus == nullptr)
    {
        return state;
    }
    state.hasFocus = true;
    if (Focusable* focusable = focus->focusable())
    {
        state.expectsKeyboardInput = focusable->acceptsKeyboardInput();
    }
    return state;
}

void StateMachineInstance::processFocusEvents()
{
    if (m_queuedFocusEvents.empty())
    {
        return;
    }

    auto events = std::move(m_queuedFocusEvents);
    m_queuedFocusEvents.clear();

    for (const auto& event : events)
    {
        auto listener = event.group->listener();
        bool isFocusEvent = event.isFocus;

        // Match listener type to event type
        if ((isFocusEvent && listener->hasListener(ListenerType::focus)) ||
            (!isFocusEvent && listener->hasListener(ListenerType::blur)))
        {
            listener->performChanges(
                this,
                ListenerInvocation::focus(event.group, event.isFocus));
        }
    }
}

void StateMachineInstance::queueSemanticEvent(SemanticListenerGroup* group,
                                              SemanticActionType actionType)
{
    m_queuedSemanticEvents.push_back({group, actionType});
    m_needsAdvance = true;
}

void StateMachineInstance::processSemanticEvents()
{
    if (m_queuedSemanticEvents.empty())
    {
        return;
    }

    auto events = std::move(m_queuedSemanticEvents);
    m_queuedSemanticEvents.clear();

    for (const auto& event : events)
    {
        if (event.group == nullptr)
        {
            continue;
        }
        auto* listener = event.group->listener();
        if (listener == nullptr)
        {
            continue;
        }
        listener->performChanges(
            this,
            ListenerInvocation::semantic(event.group, event.actionType));
    }
}

void StateMachineInstance::fireSemanticAction(uint32_t semanticNodeId,
                                              SemanticActionType actionType)
{
    // The unified SemanticManager indexes every SD in the tree — top-level,
    // nested-artboard, and data-bound list items — so this lookup handles
    // all dispatch targets uniformly. SemanticData::fire*() routes the
    // event to listeners, which queue on their own owning state machine.
    auto* mgr = semanticManager();
    if (mgr == nullptr)
    {
        return;
    }
    auto* node = mgr->nodeById(semanticNodeId);
    if (node == nullptr)
    {
        return;
    }
    auto* sd = node->semanticData();
    if (sd == nullptr)
    {
        // Boundary nodes have no owning SemanticData.
        return;
    }
    switch (actionType)
    {
        case SemanticActionType::tap:
            sd->fireSemanticTap();
            break;
        case SemanticActionType::increase:
            sd->fireSemanticIncrease();
            break;
        case SemanticActionType::decrease:
            sd->fireSemanticDecrease();
            break;
    }
}

bool StateMachineInstance::advance(float seconds, bool newFrame)
{
    RIVE_PROF_SCOPE()
    if (m_drawOrderChangeCounter !=
        m_artboardInstance->drawOrderChangeCounter())
    {
        m_drawOrderChangeCounter = m_artboardInstance->drawOrderChangeCounter();
        sortHitComponents();
    }
    if (newFrame)
    {
        processFocusEvents();
        processSemanticEvents();
        applyEvents();
        m_needsAdvance = false;
    }
    updateDataBinds(false);
    for (size_t i = 0; i < m_layerCount; i++)
    {
        if (m_layers[i].advance(seconds, newFrame))
        {
            m_needsAdvance = true;
        }
    }

    if (advanceDataBinds(seconds))
    {
        m_needsAdvance = true;
    }

    if (m_inputInstances.size() > 0)
    {
        for (auto inst : m_inputInstances)
        {
            inst->advanced();
        }
    }
    return m_needsAdvance || !m_reportedEvents.empty() ||
           !m_reportedListenerViewModels.empty();
}

void StateMachineInstance::advancedDataContext()
{
    if (m_DataContext != nullptr)
    {
        m_DataContext->advanced();
    }
}

void StateMachineInstance::reset()
{
    advancedDataContext();
    m_artboardInstance->reset();
}

bool StateMachineInstance::advanceAndApply(float seconds)
{
    return advanceAndApply(seconds, true);
}

bool StateMachineInstance::advanceAndApply(float seconds,
                                           bool advanceViewModels)
{
    RIVE_PROF_SCOPE_L(1)
    // Advancing by 0 could return false, when it shouldn't. Force keepGoing
    // to true.
    bool keepGoing = this->advance(seconds, true) || seconds == 0.0f;
    focusManager()->dropFocusIfFocusTargetHidden();
    if (m_artboardInstance->advanceInternal(
            seconds,
            AdvanceFlags::IsRoot | AdvanceFlags::Animate |
                AdvanceFlags::AdvanceNested | AdvanceFlags::NewFrame))
    {
        keepGoing = true;
    }

    for (int outerOptionC = 0; outerOptionC < 5; outerOptionC++)
    {
        if (m_artboardInstance->updatePass(true))
        {
            keepGoing = true;
        }

        // Advance all animations.
        if (this->tryChangeState())
        {
            this->advance(0.0f, false);
            keepGoing = true;
        }

        if (m_artboardInstance->advanceInternal(
                0.0f,
                AdvanceFlags::IsRoot | AdvanceFlags::Animate |
                    AdvanceFlags::AdvanceNested))
        {
            keepGoing = true;
        }
        if (advanceViewModels)
        {
            reset(); // advancedDataContext() (VM consume) + artboard reset
        }
        else
        {
            m_artboardInstance->reset(); // artboard component reset only
        }

        if (!m_artboardInstance->hasDirt(ComponentDirt::Components))
        {
            break;
        }
    }
    if (advanceViewModels)
    {
        // Advance detached scripted view models (created via scripts, not part
        // of the bound view model tree) at the end of the frame.
        m_artboardInstance->advanceScriptedViewModels();
    }
    return keepGoing || !m_reportedEvents.empty() ||
           !m_reportedListenerViewModels.empty();
}

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

void StateMachineInstance::resetState()
{
    for (size_t i = 0; i < m_layerCount; i++)
    {
        m_layers[i].resetState();
    }
}

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

void StateMachineInstance::setViewModelInstance(
    rcp<ViewModelInstance> viewModelInstance)
{
    if (viewModelInstance == nullptr)
    {
        return;
    }
    if (m_DataContext == nullptr)
    {
        m_DataContext = make_rcp<DataContext>(viewModelInstance);
        m_DataContext->addDependentContainer(this);
        return;
    }
    // The data context re-points every attached container (this state machine,
    // the artboard, and any sibling state machines sharing the context) off the
    // old main and onto the new one.
    m_DataContext->setMainViewModelInstance(viewModelInstance);
}

bool StateMachineInstance::setGlobalViewModelInstance(
    const std::string& name,
    rcp<ViewModelInstance> viewModelInstance)
{
    // A null instance is allowed: it empties the named slot below.
    auto file = m_artboardInstance->file();
    if (file == nullptr)
    {
        return false;
    }
    // The slot is addressed by the named view model (its file index), not by
    // the instance's own view model — so an override instance of a different
    // view model can be placed on the slot.
    uint32_t slotKey = file->viewModelId(name);
    if (slotKey >= file->viewModelCount())
    {
        return false;
    }
    // Only global view models get a slot; a non-global name is not a valid
    // global slot and must not be slotted.
    auto slotViewModel = file->viewModel(slotKey);
    if (slotViewModel == nullptr ||
        static_cast<ViewModelType>(slotViewModel->viewModelType()) !=
            ViewModelType::global)
    {
        return false;
    }
    if (m_DataContext == nullptr)
    {
        // Nothing to clear when there is no context yet; only create one when
        // actually placing an instance.
        if (viewModelInstance == nullptr)
        {
            return true;
        }
        m_DataContext = make_rcp<DataContext>(rcp<ViewModelInstance>(nullptr));
        m_DataContext->addDependentContainer(this);
    }
    // The data context re-points every attached container off any previous
    // instance occupying this slot and onto the new one (or empties the slot
    // when the instance is null).
    m_DataContext->setViewModelInstanceForSlot(slotKey, viewModelInstance);
    return true;
}

void StateMachineInstance::bind()
{
    if (m_DataContext == nullptr)
    {
        // No data context yet: create an empty one so the view model
        // instances it needs can be completed on the fly below.
        m_DataContext = make_rcp<DataContext>(rcp<ViewModelInstance>(nullptr));
        m_DataContext->addDependentContainer(this);
    }
    // Make sure every view model instance the data context needs exists before
    // it is applied: the main instance plus one for each global view model.
    // Any that are missing are created (completed) on the fly.
    completeViewModelInstances();
    // Apply the current data context: rebind the artboard and state machine
    // data binds in a single pass.
    m_artboardInstance->internalDataContext(m_DataContext);
    internalDataContext(m_DataContext);
}

void StateMachineInstance::completeViewModelInstances()
{
    auto file = m_artboardInstance->file();
    if (file == nullptr)
    {
        return;
    }
    // Ensure a main instance is present. The main is the entry not on the slot
    // keys; if there is none, create the artboard's default and place it first.
    if (m_DataContext->mainViewModelInstance() == nullptr)
    {
        auto main = file->createDefaultViewModelInstance(m_artboardInstance);
        if (main != nullptr)
        {
            // setMainViewModelInstance re-points every attached container onto
            // the new instance.
            m_DataContext->setMainViewModelInstance(main);
        }
    }
    // Ensure an instance exists for each global view model slot, creating any
    // missing ones. Occupancy is checked by slot key, so a cross-view-model
    // override already sitting in a slot is not treated as empty.
    for (auto* viewModel : file->globalViewModels())
    {
        uint32_t slotKey = file->viewModelId(viewModel->name());
        if (m_DataContext->instanceForSlot(slotKey) != nullptr)
        {
            continue;
        }
        auto instance = file->createDefaultViewModelInstance(viewModel);
        if (instance != nullptr)
        {
            // setViewModelInstanceForSlot re-points every attached container
            // onto the new instance.
            m_DataContext->setViewModelInstanceForSlot(slotKey, instance);
        }
    }
}

void StateMachineInstance::bindViewModelInstance(
    rcp<ViewModelInstance> viewModelInstance)
{
    if (viewModelInstance == nullptr)
    {
        clearDataContext();
        m_artboardInstance->unbind();
        return;
    }
    setViewModelInstance(std::move(viewModelInstance));
    bind();
}

rcp<ViewModelInstance> StateMachineInstance::globalViewModelInstance(
    const std::string& name)
{
    // Pure read: returns the instance in the named slot only if one has been
    // set/bound; never creates.
    if (m_DataContext == nullptr)
    {
        return nullptr;
    }
    auto file = m_artboardInstance->file();
    if (file == nullptr)
    {
        return nullptr;
    }
    return m_DataContext->instanceForSlot(file->viewModelId(name));
}

void StateMachineInstance::bindDataContext(rcp<DataContext> dataContext)
{
    clearDataContext();
    dataContext->addDependentContainer(this);
    m_artboardInstance->clearDataContext();
    m_artboardInstance->internalDataContext(dataContext);
    internalDataContext(dataContext);
}

void StateMachineInstance::inheritDataContext(rcp<DataContext> dataContext)
{
    if (dataContext == nullptr)
    {
        return;
    }
    dataContext->addDependentContainer(this);
    internalDataContext(dataContext);
}

void StateMachineInstance::dataContext(rcp<DataContext> dataContext)
{
    clearDataContext();
    internalDataContext(dataContext);
}

void StateMachineInstance::initScriptedObjects()
{
    for (auto obj : m_scriptedObjectsMap)
    {
        if (obj.second->scriptAsset() != nullptr)
        {
            if (!obj.second->userLuaInitDone())
            {
                obj.second->scriptAsset()->initScriptedObject(obj.second);
            }
            obj.second->hydrateScriptInputs();
        }
    }
}

void StateMachineInstance::internalDataContext(rcp<DataContext> dataContext)
{
    m_DataContext = dataContext;
    bindDataBindsFromContext(dataContext.get());
    for (auto listenerViewModel : m_listenerViewModels)
    {
        listenerViewModel->bindFromContext(dataContext);
    }
    for (auto& scriptedObjectItr : m_scriptedObjectsMap)
    {
        scriptedObjectItr.second->dataContext(dataContext);
    }
    initScriptedObjects();
}

void StateMachineInstance::rebind()
{
    m_artboardInstance->clearDataContext();
    m_artboardInstance->internalDataContext(m_DataContext);
    internalDataContext(m_DataContext);
};

void StateMachineInstance::clearDataContext()
{
    if (m_DataContext)
    {
        m_DataContext->removeDependentContainer(this);
        m_DataContext = nullptr;
    }
    for (auto& listenerViewModel : m_listenerViewModels)
    {
        listenerViewModel->clearDataContext();
    }
}

void StateMachineInstance::relinkDataContext()
{
    m_artboardInstance->relinkDataContext();
}

void StateMachineInstance::rebuildDataBind(DataBind* dataBind)
{
    if (dataBind->is<DataBindContext>())
    {
        dataBind->as<DataBindContext>()->bindFromContext(m_DataContext.get());
    }
};

void StateMachineInstance::unbind()
{
    clearDataContext();
    unbindDataBinds();
}

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

void StateMachineInstance::reportEvent(Event* event, float delaySeconds)
{
    m_reportedEvents.push_back(EventReport(event, delaySeconds));
}

void StateMachineInstance::reportListenerViewModel(
    ListenerViewModel* listenerViewModel)
{
    m_reportedListenerViewModels.push_back(listenerViewModel);
}

std::size_t StateMachineInstance::reportedEventCount() const
{
    return m_eventsAppliedDuringLoop.size() + m_reportedEvents.size();
}

const EventReport StateMachineInstance::reportedEventAt(std::size_t index) const
{
    if (index < m_eventsAppliedDuringLoop.size())
    {
        return m_eventsAppliedDuringLoop[index];
    }
    index -= m_eventsAppliedDuringLoop.size();
    if (index >= m_reportedEvents.size())
    {
        return EventReport(nullptr, 0.0f);
    }
    return m_reportedEvents[index];
}

void StateMachineInstance::notify(const std::vector<EventReport>& events,
                                  NestedArtboard* context)
{
    notifyEventListeners(events, context);
    updateDataBinds(false);
}

void StateMachineInstance::notifyListenerViewModels(
    const std::vector<ListenerViewModel*>& events)
{
    if (events.size() > 0)
    {
        for (auto& listenerViewModel : events)
        {
            listenerViewModel->listener()->performChanges(
                this,
                ListenerInvocation::viewModelChange(listenerViewModel));
        }
    }
}

void StateMachineInstance::notifyEventListeners(
    const std::vector<EventReport>& events,
    NestedArtboard* source)
{
    if (events.size() > 0)
    {
        // We trigger the listeners in order
        for (size_t i = 0; i < m_machine->listenerCount(); i++)
        {
            auto listener = m_machine->listener(i);
            auto target = artboard()->resolve(listener->targetId());
            if (listener != nullptr &&
                listener->hasListener(ListenerType::event) &&
                (source == nullptr || source == target))
            {
                for (const auto event : events)
                {
                    auto sourceArtboard = source == nullptr
                                              ? artboard()
                                              : source->artboardInstance();

                    // NOTE: this issue can't happen anymore because a new
                    // fix in the editor prevents selecting other artboard
                    // as target. But the fix is kept here to fix older
                    // files. listener->eventId() can point to an id from an
                    // event in the context of this artboard or the
                    // context of a nested artboard. Because those ids
                    // belong to different contexts, they can have the
                    // same value. So when the eventId is resolved
                    // within one context, but actually pointing to the
                    // other, it can return the wrong event object. If,
                    // by chance, that event exists in the other
                    // context, and is being reported, it will trigger
                    // the wrong set of actions. This validation makes
                    // sure that a listener must be targetting the
                    // current artboard to disambiguate between external
                    // and internal events.
                    if (source == nullptr)
                    {
                        auto target =
                            sourceArtboard->resolve(listener->targetId());
                        if (target && target != artboard() &&
                            !target->is<Event>())
                        {
                            continue;
                        }
                    }
                    if (listener->is<StateMachineListenerSingle>())
                    {
                        auto listenerEvent = sourceArtboard->resolve(
                            listener->as<StateMachineListenerSingle>()
                                ->eventId());
                        if (listenerEvent == event.event())
                        {
                            listener->performChanges(
                                this,
                                ListenerInvocation::reportedEvent(
                                    event.event(),
                                    event.secondsDelay()));
                            break;
                        }
                    }
                    else
                    {
                        size_t index = 0;
                        while (index < listener->listenerInputTypeCount())
                        {
                            auto listenerInputType =
                                listener->listenerInputType(index);
                            if (listenerInputType->is<ListenerInputTypeEvent>())
                            {

                                auto listenerInputTypeEvent =
                                    listenerInputType
                                        ->as<ListenerInputTypeEvent>();
                                auto listenerEvent = sourceArtboard->resolve(
                                    listenerInputTypeEvent->eventId());
                                if (listenerEvent == event.event())
                                {
                                    listener->performChanges(
                                        this,
                                        ListenerInvocation::reportedEvent(
                                            event.event(),
                                            event.secondsDelay()));
                                    break;
                                }
                            }
                            index += 1;
                        }
                    }
                }
            }
        }
        // Bubble the event up to parent artboard state machines
        // immediately
        for (auto listener : nestedEventListeners())
        {
            listener->notify(events, nestedArtboard());
        }

        for (auto report : events)
        {
            auto event = report.event();
            if (event->is<AudioEvent>())
            {
                event->as<AudioEvent>()->play();
            }
        }
    }
}

void StateMachineInstance::enablePointerEvents(int pointerId)
{
    for (const auto& hitShape : m_hitComponents)
    {
        hitShape->enablePointerEvents(pointerId);
    }
}

void StateMachineInstance::disablePointerEvents(int pointerId)
{
    for (const auto& hitShape : m_hitComponents)
    {
        hitShape->disablePointerEvents(pointerId);
    }
}

BindableProperty* StateMachineInstance::bindablePropertyInstance(
    BindableProperty* bindableProperty) const
{
    auto bindablePropertyInstance =
        m_bindablePropertyInstances.find(bindableProperty);
    if (bindablePropertyInstance == m_bindablePropertyInstances.end())
    {
        return nullptr;
    }
    return bindablePropertyInstance->second;
}

DataBind* StateMachineInstance::bindableDataBindToSource(
    BindableProperty* bindableProperty) const
{
    auto dataBind = m_bindableDataBindsToSource.find(bindableProperty);
    if (dataBind == m_bindableDataBindsToSource.end())
    {
        return nullptr;
    }
    return dataBind->second;
}

DataBind* StateMachineInstance::bindableDataBindToTarget(
    BindableProperty* bindableProperty) const
{
    auto dataBind = m_bindableDataBindsToTarget.find(bindableProperty);
    if (dataBind == m_bindableDataBindsToTarget.end())
    {
        return nullptr;
    }
    return dataBind->second;
}

BindablePropertyNumber* StateMachineInstance::findTransitionPropertyInstance(
    const StateTransition* transition,
    uint32_t propertyKey) const
{
    auto it = m_transitionPropertyInstances.find(transition);
    if (it != m_transitionPropertyInstances.end())
    {
        auto propIt = it->second.find(propertyKey);
        if (propIt != it->second.end())
        {
            return propIt->second;
        }
    }
    return nullptr;
}

// The BindableProperty value property key matching a keyframe's value type, or
// 0 for unsupported keyframe types (e.g. id/uint), which are left unbound.
static uint32_t keyFrameHolderPropertyKey(uint16_t keyFrameType)
{
    switch (keyFrameType)
    {
        case KeyFrameDoubleBase::typeKey:
            return BindablePropertyNumberBase::propertyValuePropertyKey;
        case KeyFrameColorBase::typeKey:
            return BindablePropertyColorBase::propertyValuePropertyKey;
        case KeyFrameBoolBase::typeKey:
            return BindablePropertyBooleanBase::propertyValuePropertyKey;
        case KeyFrameStringBase::typeKey:
            return BindablePropertyStringBase::propertyValuePropertyKey;
        default:
            return 0;
    }
}

// Creates the BindableProperty holder matching a keyframe's value type.
static BindableProperty* makeKeyFrameValueHolder(uint16_t keyFrameType)
{
    switch (keyFrameType)
    {
        case KeyFrameDoubleBase::typeKey:
            return new BindablePropertyNumber();
        case KeyFrameColorBase::typeKey:
            return new BindablePropertyColor();
        case KeyFrameBoolBase::typeKey:
            return new BindablePropertyBoolean();
        case KeyFrameStringBase::typeKey:
            return new BindablePropertyString();
        default:
            return nullptr;
    }
}

void StateMachineInstance::buildStateKeyFrameBinds(StateInstance* stateInstance)
{
    if (stateInstance == nullptr || m_artboardInstance == nullptr)
    {
        return;
    }
    // Keyframe-targeting data binds are serialized on the source artboard (they
    // target the shared, never-cloned keyframes), so resolve them from there.
    const Artboard* source = m_artboardInstance->artboardSource();
    if (source == nullptr)
    {
        return;
    }

    // Pre-index the source artboard's keyframe-targeting data binds once, keyed
    // by their target keyframe. A keyframe holds a single value, so keep the
    // first bind per target (emplace does not overwrite). This turns the
    // per-keyframe lookup below from an O(numDataBinds) scan into O(1), so
    // building a state's binds is O(numKeyFrames + numDataBinds) instead of
    // O(numKeyFrames * numDataBinds). Filtering to keyframe targets keeps the
    // index small (most data binds target components, not keyframes).
    std::unordered_map<const Core*, DataBind*> firstBindByTarget;
    for (auto dataBind : source->dataBinds())
    {
        auto target = dataBind->target();
        if (target == nullptr || !target->is<KeyFrame>())
        {
            continue;
        }
        firstBindByTarget.emplace(target, dataBind);
    }
    if (firstBindByTarget.empty())
    {
        // No keyframe is data bound anywhere; skip the keyframe walk entirely.
        return;
    }

    stateInstance->forEachAnimationInstance(
        [this, stateInstance, &firstBindByTarget](
            LinearAnimationInstance* animationInstance) {
            const LinearAnimation* animation = animationInstance->animation();
            if (animation == nullptr)
            {
                return;
            }
            for (size_t o = 0; o < animation->numKeyedObjects(); o++)
            {
                const KeyedObject* keyedObject = animation->getObject(o);
                if (keyedObject == nullptr)
                {
                    continue;
                }
                for (size_t p = 0; p < keyedObject->numKeyedProperties(); p++)
                {
                    const KeyedProperty* keyedProperty =
                        keyedObject->getProperty(p);
                    if (keyedProperty == nullptr)
                    {
                        continue;
                    }
                    for (size_t k = 0; k < keyedProperty->numKeyFrames(); k++)
                    {
                        KeyFrame* keyframe = keyedProperty->getKeyFrame(k);
                        uint32_t holderPropertyKey =
                            keyFrameHolderPropertyKey(keyframe->coreType());
                        if (holderPropertyKey == 0)
                        {
                            continue;
                        }
                        auto found = firstBindByTarget.find(keyframe);
                        if (found == firstBindByTarget.end())
                        {
                            continue;
                        }
                        DataBind* dataBind = found->second;
                        auto holder =
                            makeKeyFrameValueHolder(keyframe->coreType());
                        animationInstance->addKeyFrameValueHolder(keyframe,
                                                                  holder);
                        auto dataBindClone =
                            static_cast<DataBind*>(dataBind->clone());
                        dataBindClone->file(dataBind->file());
                        dataBindClone->target(holder);
                        dataBindClone->propertyKey(holderPropertyKey);
                        dataBindClone->initialize();
                        if (dataBind->converter() != nullptr)
                        {
                            dataBindClone->converter(dataBind->converter()
                                                         ->clone()
                                                         ->as<DataConverter>());
                        }
                        addDataBind(dataBindClone);
                        m_stateKeyFrameDataBinds[stateInstance].push_back(
                            dataBindClone);
                    }
                }
            }
        });
}

void StateMachineInstance::removeStateKeyFrameBinds(
    StateInstance* stateInstance)
{
    auto it = m_stateKeyFrameDataBinds.find(stateInstance);
    if (it == m_stateKeyFrameDataBinds.end())
    {
        return;
    }
    for (auto* dataBind : it->second)
    {
        removeDataBind(dataBind);
        delete dataBind;
    }
    m_stateKeyFrameDataBinds.erase(it);
}

bool StateMachineInstance::hasFocusNodes()
{
    auto* fm = focusManager();
    assert(fm != nullptr);
    return fm->hasFocusableContent();
}

bool StateMachineInstance::focusNext()
{
    auto* fm = focusManager();
    assert(fm != nullptr);
    return fm->focusNext();
}

bool StateMachineInstance::focusPrevious()
{
    auto* fm = focusManager();
    assert(fm != nullptr);
    return fm->focusPrevious();
}

void StateMachineInstance::clearFocus()
{
    auto* fm = focusManager();
    assert(fm != nullptr);
    fm->clearFocus();
}
