#include "rive/animation/keyed_property.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/animation/keyframe.hpp"
#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/animation/interpolating_keyframe.hpp"
#include "rive/animation/keyed_callback_reporter.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/keyed_object_importer.hpp"
#include "rive/importers/linear_animation_importer.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/generated/core_registry.hpp"
#include <algorithm>

using namespace rive;

KeyedProperty::KeyedProperty() {}
KeyedProperty::~KeyedProperty() {}

void KeyedProperty::addKeyFrame(std::unique_ptr<KeyFrame> keyframe)
{
  m_keyFrames.push_back(std::move(keyframe));
}

// `addKeyFrameForEditor`, `clearEditorKeyFrames`, `sortEditorKeyFrames`
// and `editorClosestFrameIndex` live in the editor_native package
// (`src/editor/animation/keyed_property_editor.cpp`) so the runtime-
// only build never compiles or links them. The declarations stay on
// `KeyedProperty` (under `#ifdef WITH_RIVE_EDITOR` in the header)
// because `apply()` below still uses `m_editorKeyFrames` directly when
// the editor list is populated — the runtime build just sees an empty
// vector and falls through to the runtime-owned `m_keyFrames`.

int KeyedProperty::closestFrameIndex(float seconds, int exactOffset) const
{
  int mid = 0;
  float closestSeconds = 0;
  int start = 0;
  auto numKeyFrames = static_cast<int>(m_keyFrames.size());
  int end = numKeyFrames - 1;

  // If it's the last keyframe, we skip the binary search
  if (seconds > m_keyFrames[end]->seconds())
  {
    return end + 1;
  }

  while (start <= end)
  {
    mid = (start + end) >> 1;
    closestSeconds = m_keyFrames[mid]->seconds();
    if (closestSeconds < seconds)
    {
      start = mid + 1;
    }
    else if (closestSeconds > seconds)
    {
      end = mid - 1;
    }
    else
    {
      return mid + exactOffset;
    }
  }
  return start;
}

void KeyedProperty::reportKeyedCallbacks(
    KeyedCallbackReporter* reporter,
    uint32_t objectId,
    float secondsFrom,
    float secondsTo,
    bool isAtStartFrame) const
{
  if (secondsFrom == secondsTo)
  {
    return;
  }
  bool isForward = secondsFrom <= secondsTo;
  int fromExactOffset = 0;
  int toExactOffset = isForward ? 1 : 0;
  if (isForward)
  {
    if (!isAtStartFrame)
    {
      fromExactOffset = 1;
    }
  }
  else
  {
    if (isAtStartFrame)
    {
      fromExactOffset = 1;
    }
  }
  int idx = closestFrameIndex(secondsFrom, fromExactOffset);
  int idxTo = closestFrameIndex(secondsTo, toExactOffset);

  if (idxTo < idx)
  {
    auto swap = idx;
    idx = idxTo;
    idxTo = swap;
  }
  while (idxTo > idx)
  {
    const std::unique_ptr<KeyFrame>& frame = m_keyFrames[idx];
    reporter->reportKeyedCallback(
        objectId,
        propertyKey(),
        secondsTo - frame->seconds());
    idx++;
  }
}

void KeyedProperty::apply(
    Core* object,
    float seconds,
    float mix,
    const LinearAnimationInstance* context)
{
  apply(object, seconds, mix, context, InterpolatorHost::from(object));
}

void KeyedProperty::apply(
    Core* object,
    float seconds,
    float mix,
    const LinearAnimationInstance* context,
    InterpolatorHost* interpolatorHost)
{
#ifdef WITH_RIVE_EDITOR
  // A given KeyedProperty instance is either runtime-loaded (uses
  // m_keyFrames unique_ptr owned) or coop-loaded (uses
  // m_editorKeyFrames non-owning). Pick the populated one; the
  // binary-search / interpolate logic below operates on whichever
  // side holds the data. Both-populated can't happen in practice
  // — a single property either lives in the importer chain or in
  // the arena, never both.
  const bool useEditor = m_keyFrames.empty() && !m_editorKeyFrames.empty();
  const size_t frameCount = useEditor ? m_editorKeyFrames.size()
                                      : m_keyFrames.size();
  // Editor edge case: the user just deleted every kf in this
  // property (e.g. via kDeleteKeyFrameSelection). The KeyedProperty
  // Core itself stays alive — it's only orphaned when its parent
  // KeyedObject gets deleted — but its editor list is empty, and
  // the binary search below would read `m_editorKeyFrames[-1]`.
  // Skip with no overlay so the property reverts to its design-
  // time value on the next frame.
  if (frameCount == 0)
    return;
  auto frameAt = [this, useEditor](int i) -> InterpolatingKeyFrame* {
    return static_cast<InterpolatingKeyFrame*>(
        useEditor ? m_editorKeyFrames[i] : m_keyFrames[i].get());
  };
  const int closestIdx = useEditor ? editorClosestFrameIndex(seconds)
                                   : closestFrameIndex(seconds);
#else
  assert(!m_keyFrames.empty());
  const size_t frameCount = m_keyFrames.size();
  auto frameAt = [this](int i) -> InterpolatingKeyFrame* {
    return static_cast<InterpolatingKeyFrame*>(m_keyFrames[i].get());
  };
  const int closestIdx = closestFrameIndex(seconds);
#endif

  auto actualMix = mix;
  if (interpolatorHost != nullptr &&
      interpolatorHost->overridesKeyedInterpolation(propertyKey()))
  {
    actualMix = 1.0f;
  }

  int idx = closestIdx;
  int pk = propertyKey();

  if (idx == 0)
  {
    frameAt(0)->apply(object, pk, actualMix, context);
  }
  else
  {
    if (idx < static_cast<int>(frameCount))
    {
      InterpolatingKeyFrame* fromFrame = frameAt(idx - 1);
      InterpolatingKeyFrame* toFrame = frameAt(idx);
      if (seconds == toFrame->seconds())
      {
        toFrame->apply(object, pk, actualMix, context);
      }
      else
      {
        if (fromFrame->interpolationType() == 0)
        {
          fromFrame->apply(object, pk, actualMix, context);
        }
        else
        {
          fromFrame->applyInterpolation(
              object,
              pk,
              seconds,
              toFrame,
              actualMix,
              context);
        }
      }
    }
    else
    {
      frameAt(idx - 1)->apply(object, pk, actualMix, context);
    }
  }
}

StatusCode KeyedProperty::onAddedDirty(CoreContext* context)
{
  StatusCode code;
  for (auto& keyframe : m_keyFrames)
  {
    if ((code = keyframe->onAddedDirty(context)) != StatusCode::Ok)
    {
      return code;
    }
  }
#ifdef WITH_RIVE_EDITOR
  for (auto* keyframe : m_editorKeyFrames)
  {
    keyframe->onAddedDirty(context);
  }
#endif
  return StatusCode::Ok;
}

StatusCode KeyedProperty::onAddedClean(CoreContext* context)
{
  StatusCode code;
  for (auto& keyframe : m_keyFrames)
  {
    if ((code = keyframe->onAddedClean(context)) != StatusCode::Ok)
    {
      return code;
    }
  }
#ifdef WITH_RIVE_EDITOR
  for (auto* keyframe : m_editorKeyFrames)
  {
    keyframe->onAddedClean(context);
  }
#endif
  return StatusCode::Ok;
}

StatusCode KeyedProperty::import(ImportStack& importStack)
{
  auto importer = importStack.latest<KeyedObjectImporter>(
      KeyedObjectBase::typeKey);
  if (importer == nullptr)
  {
    return StatusCode::MissingObject;
  }
  importer->addKeyedProperty(std::unique_ptr<KeyedProperty>(this));
  if (CoreRegistry::isCallback(propertyKey()))
  {
    auto animationImporter = importStack.latest<LinearAnimationImporter>(
        LinearAnimationBase::typeKey);
    if (animationImporter != nullptr)
    {
      animationImporter->animation()->hasKeyedCallbacks(true);
    }
  }
  return Super::import(importStack);
}
