#include "rive/animation/listener_invocation.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/core/binary_reader.hpp"
#include "rive/input/focus_manager.hpp"
#include "rive/input/gamepad_batch.hpp"
#include "rive/input/gamepad_snapshot.hpp"
#include "rive/input/standard_gamepad.hpp"
#include "rive/scripted/scripted_drawable.hpp"
#include "rive/span.hpp"
// Defines StateMachineInstance's SMIInputExtras cluster, which owns the
// embedder gamepad snapshots and the gamepad-aware scripted drawables.
#include "rive/animation/state_machine_instance_clusters.hpp"

namespace rive
{

static void recomputeButtonMaskFromValues(GamepadSnapshot& s)
{
    s.buttonMask = 0;
    for (size_t i = 0; i < s.buttonValues.size(); i++)
    {
        if (s.buttonValues[i] >= 0.5f)
        {
            s.buttonMask |= (uint64_t(1) << i);
        }
    }
}

static void fillStandardIntent(const GamepadSnapshot& snap,
                               GamepadEventInvocation& ev)
{
    ev.hasStandardButtonIntent = false;
    ev.hasStandardAxisIntent = false;
    if (snap.mapping != GamepadMappingKind::standard)
    {
        return;
    }
    if (ev.change.kind == GamepadInputChangeKind::button)
    {
        if (ev.change.index <=
            static_cast<uint8_t>(StandardGamepadButton::start))
        {
            ev.hasStandardButtonIntent = true;
            ev.standardButton =
                static_cast<StandardGamepadButton>(ev.change.index);
        }
    }
    else
    {
        if (ev.change.index <=
            static_cast<uint8_t>(StandardGamepadAxis::rightTrigger))
        {
            ev.hasStandardAxisIntent = true;
            ev.standardAxis = static_cast<StandardGamepadAxis>(ev.change.index);
        }
    }
}

static bool readConnectedPayload(BinaryReader& reader,
                                 GamepadSnapshot& outSnapshot)
{
    outSnapshot = GamepadSnapshot{};
    outSnapshot.deviceId = static_cast<int32_t>(reader.readUint32());
    const uint8_t mappingByte = reader.readByte();
    const uint8_t nButtons = reader.readByte();
    const uint8_t nAxes = reader.readByte();
    reader.readByte(); // 1-byte padding to align the float arrays.
    if (reader.hasError() || nButtons > kGamepadBatchMaxButtons ||
        nAxes > kGamepadBatchMaxAxes)
    {
        return false;
    }
    outSnapshot.mapping = mappingByte == 0 ? GamepadMappingKind::standard
                                           : GamepadMappingKind::unknown;
    outSnapshot.buttonValues.resize(nButtons);
    outSnapshot.axes.resize(nAxes);
    for (uint8_t b = 0; b < nButtons; b++)
    {
        outSnapshot.buttonValues[b] = reader.readFloat32();
    }
    for (uint8_t a = 0; a < nAxes; a++)
    {
        outSnapshot.axes[a] = reader.readFloat32();
    }
    if (reader.hasError())
    {
        return false;
    }
    // buttonMask is not on the wire — derive it from the per-button values.
    recomputeButtonMaskFromValues(outSnapshot);
    return true;
}

static bool applyUpdateChange(GamepadSnapshot& snap,
                              const GamepadInputChange& ch)
{
    if (ch.kind == GamepadInputChangeKind::button)
    {
        if (ch.index >= kGamepadBatchMaxButtons)
        {
            return false;
        }
        if (snap.buttonValues.size() <= ch.index)
        {
            snap.buttonValues.resize(ch.index + 1, 0.f);
        }
        snap.buttonValues[ch.index] = ch.value;
        recomputeButtonMaskFromValues(snap);
    }
    else
    {
        if (ch.index >= kGamepadBatchMaxAxes)
        {
            return false;
        }
        if (snap.axes.size() <= ch.index)
        {
            snap.axes.resize(ch.index + 1, 0.f);
        }
        snap.axes[ch.index] = ch.value;
    }
    return true;
}

static GamepadEventInvocation makeEventInvocation(
    const GamepadSnapshot& afterApply,
    const GamepadInputChange& ch)
{
    GamepadEventInvocation ev;
    ev.fullState = afterApply;
    ev.change = ch;
    fillStandardIntent(afterApply, ev);
    return ev;
}

// Decode a little-endian binary batch of gamepad events produced by the
// embedder (e.g. the JS runtime — see registerGamepadInteractions.ts) and
// dispatch them through the focus manager.
//
// Wire format (all multi-byte values little-endian, fixed-width — no LEB128):
//   uint32  version  -- must equal kGamepadBatchWireVersion
//   then a stream of records, each starting with a 1-byte GamepadRecordType:
//
//     connected (0):
//       int32   deviceId
//       uint8   mapping           (0 = standard, else unknown)
//       uint8   nButtons          (<= kGamepadBatchMaxButtons)
//       uint8   nAxes             (<= kGamepadBatchMaxAxes)
//       uint8   padding           (alignment filler)
//       float32 buttonValues[nButtons]
//       float32 axes[nAxes]
//
//     update (1):
//       int32   deviceId
//       uint8   nChanges
//       repeated nChanges times:
//         uint8   kind            (0 = button, 1 = axis)
//         uint8   index
//         float32 value
//
//     disconnected (2):
//       int32   deviceId
//
// Returns false (and stops dispatching) on any malformed record: short read,
// wrong version, unknown device on update, out-of-range button/axis index,
// or unknown record type. A truncated batch leaves any records dispatched so
// far in place.
bool StateMachineInstance::submitGamepadsFromBuffer(const uint8_t* data,
                                                    size_t n)
{
    if (data == nullptr)
    {
        return false;
    }
    BinaryReader reader(Span<const uint8_t>(data, n));
    const uint32_t version = reader.readUint32();
    if (reader.hasError() || version != kGamepadBatchWireVersion)
    {
        return false;
    }
    FocusManager* fm = focusManager();
    if (fm == nullptr)
    {
        return false;
    }
    // An embedder submitting a batch is exactly the moment gamepad state
    // starts existing on this instance, so allocate the cluster up front and
    // keep the pointer for the whole drain.
    SMIInputExtras& extras = ensureInputExtras();
    // reachedEnd() returns true once the cursor hits end-of-buffer OR the
    // reader has flagged an overflow, so any partial-record read inside the
    // loop will both `return false` and naturally terminate iteration.
    while (!reader.reachedEnd())
    {
        const uint8_t typeByte = reader.readByte();
        if (reader.hasError())
        {
            return false;
        }
        const auto rec = static_cast<GamepadRecordType>(typeByte);
        switch (rec)
        {
            case GamepadRecordType::connected:
            {
                GamepadSnapshot snap;
                if (!readConnectedPayload(reader, snap))
                {
                    return false;
                }
                extras.embedderGamepads[snap.deviceId] = snap;
                {
                    auto invocation =
                        ListenerInvocation::gamepadConnected(snap);
                    ScriptedDrawable* dispatched = nullptr;
                    (void)fm->gamepadDispatch(invocation, &dispatched);
                    broadcastGamepadToScriptedDrawables(invocation, dispatched);
                }
                break;
            }
            case GamepadRecordType::update:
            {
                const int32_t deviceId =
                    static_cast<int32_t>(reader.readUint32());
                const uint8_t nChanges = reader.readByte();
                if (reader.hasError())
                {
                    return false;
                }
                // Updates must target a gamepad we've previously seen
                // connected; otherwise we have no snapshot to mutate.
                auto it = extras.embedderGamepads.find(deviceId);
                if (it == extras.embedderGamepads.end())
                {
                    return false;
                }
                std::vector<GamepadInputChange> changes;
                changes.reserve(nChanges);
                for (uint8_t i = 0; i < nChanges; i++)
                {
                    const uint8_t chKindB = reader.readByte();
                    const uint8_t chIndex = reader.readByte();
                    const float fval = reader.readFloat32();
                    if (reader.hasError())
                    {
                        return false;
                    }
                    GamepadInputChange ch;
                    ch.kind = chKindB == 0 ? GamepadInputChangeKind::button
                                           : GamepadInputChangeKind::axis;
                    ch.index = chIndex;
                    ch.value = fval;
                    changes.push_back(ch);
                }
                // Apply all changes to the stored snapshot first so that every
                // dispatched event sees the same fully-updated `fullState`...
                GamepadSnapshot& snap = it->second;
                for (const auto& ch : changes)
                {
                    if (!applyUpdateChange(snap, ch))
                    {
                        return false;
                    }
                }
                // ...then dispatch one event per change carrying that final
                // state plus the specific change that occurred.
                const GamepadSnapshot finalSnap = snap;
                for (const auto& ch : changes)
                {
                    GamepadEventInvocation evi =
                        makeEventInvocation(finalSnap, ch);
                    auto invocation =
                        ListenerInvocation::gamepadEvent(std::move(evi));
                    ScriptedDrawable* dispatched = nullptr;
                    (void)fm->gamepadDispatch(invocation, &dispatched);
                    broadcastGamepadToScriptedDrawables(invocation, dispatched);
                }
                break;
            }
            case GamepadRecordType::disconnected:
            {
                const int32_t deviceId =
                    static_cast<int32_t>(reader.readUint32());
                if (reader.hasError())
                {
                    return false;
                }
                extras.embedderGamepads.erase(deviceId);
                {
                    auto invocation =
                        ListenerInvocation::gamepadDisconnected(deviceId);
                    ScriptedDrawable* dispatched = nullptr;
                    (void)fm->gamepadDispatch(invocation, &dispatched);
                    broadcastGamepadToScriptedDrawables(invocation, dispatched);
                }
                break;
            }
            default:
                // Unknown record type — wire format mismatch, bail out.
                return false;
        }
    }
    return true;
}

HitResult StateMachineInstance::broadcastGamepadToScriptedDrawables(
    const ListenerInvocation& invocation,
    ScriptedDrawable* alreadyDispatched)
{
    bool hitSomething = false;
    bool hitOpaque = false;
    // Walk m_hitComponents purely for the nested-propagation overrides
    // (HitNestedArtboard / HitArtboardComponentList recurse into their
    // child SMIs). HitScriptedDrawable's gamepad path is intentionally a
    // no-op — direct dispatch happens via gamepadScriptedDrawables below
    // so scripts without pointer handlers are still reached.
    for (const auto& hitShape : m_hitComponents)
    {
        HitResult hitResult =
            hitShape->processGamepadInvocation(invocation, alreadyDispatched);
        if (hitResult != HitResult::none)
        {
            hitSomething = true;
            if (hitResult == HitResult::hitOpaque)
            {
                hitOpaque = true;
            }
        }
    }

#ifdef WITH_RIVE_SCRIPTING
    // Null whenever no script in this artboard declared a gamepad handler,
    // which is the common case — nothing to broadcast to.
    if (auto* extras = inputExtras())
    {
        for (ScriptedDrawable* drawable : extras->gamepadScriptedDrawables)
        {
            if (drawable == nullptr || drawable == alreadyDispatched)
            {
                continue;
            }
            switch (invocation.kind())
            {
                case ListenerInvocationKind::gamepadConnected:
                    if (!drawable->wantsGamePadConnect())
                    {
                        continue;
                    }
                    break;
                case ListenerInvocationKind::gamepadEvent:
                    if (!drawable->wantsGamePadEvent())
                    {
                        continue;
                    }
                    break;
                case ListenerInvocationKind::gamepadDisconnected:
                    if (!drawable->wantsGamePadDisconnect())
                    {
                        continue;
                    }
                    break;
                default:
                    continue;
            }
            if (drawable->gamepadDispatch(invocation))
            {
                hitSomething = true;
            }
        }
    }
#endif

    return hitSomething ? hitOpaque ? HitResult::hitOpaque : HitResult::hit
                        : HitResult::none;
}
} // namespace rive
