#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
