#include "rive/animation/keyed_object.hpp"
#include "rive/animation/keyed_property.hpp"
#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/artboard.hpp"
#include "rive/layout_component.hpp"
#include "rive/importers/linear_animation_importer.hpp"
#include "rive/generated/core_registry.hpp"

using namespace rive;

KeyedObject::KeyedObject() {}
KeyedObject::~KeyedObject() {}

void KeyedObject::addKeyedProperty(std::unique_ptr<KeyedProperty> property)
{
  m_keyedProperties.push_back(std::move(property));
}

StatusCode KeyedObject::onAddedDirty(CoreContext* context)
{
  // Make sure we're keying a valid object.
  Core* coreObject = context->resolve(objectId());
  if (coreObject == nullptr)
  {
    return StatusCode::MissingObject;
  }
  // `clip` is animatable; a layout whose clip is keyed needs its
  // DrawableProxy up front so it exists before the artboard's one-time proxy
  // injection, even while clip is currently false. This runs on the source
  // only (instances share animations); LayoutComponent::clone carries the
  // flag to instances.
  const bool isLayout = coreObject->is<LayoutComponent>();

  for (auto itr = m_keyedProperties.begin(); itr != m_keyedProperties.end();)
  {
    auto& property = *itr;
    // Validate coreObject supports propertyKey, if not remove it from the
    // property keys.
    if (!CoreRegistry::objectSupportsProperty(
            coreObject,
            property->propertyKey()))
    {
      itr = m_keyedProperties.erase(itr);
      continue;
    }
    if (isLayout &&
        property->propertyKey() == LayoutComponentBase::clipPropertyKey)
    {
      coreObject->as<LayoutComponent>()->markClipMayBeDynamic();
    }
    StatusCode code;
    if ((code = property->onAddedDirty(context)) != StatusCode::Ok)
    {
      return code;
    }
    itr++;
  }
#ifdef WITH_RIVE_EDITOR
  // The editor list is rebuilt by `finalizeBatch` AFTER Pass 3
  // onAddedDirty runs, so at the time the dispatcher calls us on a
  // freshly-hydrated KeyedObject it's still empty. On subsequent
  // finalizeBatch runs (new coop batch), the editor list carries
  // the previously-wired coop keyed properties; walking it again
  // here keeps CoreRegistry::objectSupportsProperty pruning
  // consistent with the runtime path.
  for (auto itr = m_editorKeyedProperties.begin();
       itr != m_editorKeyedProperties.end();)
  {
    auto* property = *itr;
    if (!CoreRegistry::objectSupportsProperty(
            coreObject,
            property->propertyKey()))
    {
      itr = m_editorKeyedProperties.erase(itr);
      continue;
    }
    property->onAddedDirty(context);
    itr++;
  }
#endif
  return StatusCode::Ok;
}

StatusCode KeyedObject::onAddedClean(CoreContext* context)
{
  for (auto& property : m_keyedProperties)
  {
    property->onAddedClean(context);
  }
#ifdef WITH_RIVE_EDITOR
  for (auto* property : m_editorKeyedProperties)
  {
    property->onAddedClean(context);
  }
#endif
  return StatusCode::Ok;
}

// `addKeyedPropertyForEditor` and `clearEditorKeyedProperties` live in
// `editor_native/native/src/editor/animation/keyed_object_editor.cpp`
// — see the matching comment in `keyed_property.cpp`.

void KeyedObject::reportKeyedCallbacks(
    KeyedCallbackReporter* reporter,
    float secondsFrom,
    float secondsTo,
    bool isAtStartFrame) const
{
  for (const std::unique_ptr<KeyedProperty>& property : m_keyedProperties)
  {
    if (!CoreRegistry::isCallback(property->propertyKey()))
    {
      continue;
    }
    property->reportKeyedCallbacks(
        reporter,
        objectId(),
        secondsFrom,
        secondsTo,
        isAtStartFrame);
  }
#ifdef WITH_RIVE_EDITOR
  for (auto* property : m_editorKeyedProperties)
  {
    if (!CoreRegistry::isCallback(property->propertyKey()))
    {
      continue;
    }
    property->reportKeyedCallbacks(
        reporter,
        objectId(),
        secondsFrom,
        secondsTo,
        isAtStartFrame);
  }
#endif
}

void KeyedObject::apply(
    Artboard* artboard,
    float time,
    float mix,
    const LinearAnimationInstance* context)
{
  Core* object = artboard->resolve(objectId());
  if (object == nullptr)
  {
    return;
  }
  // Every property here keys the same object; ask it once.
  InterpolatorHost* interpolatorHost = InterpolatorHost::from(object);
  for (std::unique_ptr<KeyedProperty>& property : m_keyedProperties)
  {
    if (CoreRegistry::isCallback(property->propertyKey()))
    {
      continue;
    }
    property->apply(object, time, mix, context, interpolatorHost);
  }
#ifdef WITH_RIVE_EDITOR
  for (auto* property : m_editorKeyedProperties)
  {
    if (CoreRegistry::isCallback(property->propertyKey()))
    {
      continue;
    }
    property->apply(object, time, mix);
  }
#endif
}

StatusCode KeyedObject::import(ImportStack& importStack)
{
  auto importer = importStack.latest<LinearAnimationImporter>(
      LinearAnimationBase::typeKey);
  if (importer == nullptr)
  {
    return StatusCode::MissingObject;
  }
  // we transfer ownership of ourself to the importer!
  importer->addKeyedObject(std::unique_ptr<KeyedObject>(this));
  return Super::import(importStack);
}