#include "rive/joystick.hpp"
#include "rive/artboard.hpp"
#include "rive/transform_component.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/linear_animation_instance.hpp"

using namespace rive;

Joystick::Joystick() = default;
Joystick::~Joystick() = default;

StatusCode Joystick::onAddedDirty(CoreContext* context)
{
  StatusCode status = Super::onAddedDirty(context);
  if (status != StatusCode::Ok)
  {
    return status;
  }
  if (handleSourceId() != Core::emptyId)
  {
    auto coreObject = context->resolve(handleSourceId());
    if (coreObject == nullptr || !coreObject->is<TransformComponent>())
    {
      return StatusCode::MissingObject;
    }
    m_handleSource = static_cast<TransformComponent*>(coreObject);
  }

  return StatusCode::Ok;
}

StatusCode Joystick::onAddedClean(CoreContext* context)
{
  m_xAnimation = artboard()->animation(xId());
  m_yAnimation = artboard()->animation(yId());

  // On an artboard instance, create a playback context per animation so that
  // data-bound keyframe values resolve when the joystick applies them (the
  // shared LinearAnimation is applied directly, with no scene driving it).
  // The source artboard is never played, so skip it (and it isn't an
  // ArtboardInstance to construct the context against).
  if (artboard()->isInstance())
  {
    auto* instance = static_cast<ArtboardInstance*>(artboard());
    if (m_xAnimation != nullptr)
    {
      m_xAnimationInstance = std::make_unique<LinearAnimationInstance>(
          m_xAnimation,
          instance);
    }
    if (m_yAnimation != nullptr)
    {
      m_yAnimationInstance = std::make_unique<LinearAnimationInstance>(
          m_yAnimation,
          instance);
    }
  }

  return StatusCode::Ok;
}

void Joystick::buildDependencies()
{
  // We only need to update if we're in world space (and that is only required
  // at runtime if we have a custom handle source).
  if (m_handleSource != nullptr && parent() != nullptr)
  {
    parent()->addDependent(this);
    m_handleSource->addDependent(this);
  }
}

void Joystick::update(ComponentDirt value)
{
  if (m_handleSource == nullptr)
  {
    return;
  }
  if (hasDirt(value, ComponentDirt::WorldTransform | ComponentDirt::Transform))
  {
    Mat2D world = Mat2D::fromTranslate(posX(), posY());
    if (parent() != nullptr && parent()->is<WorldTransformComponent>())
    {
      world = parent()->as<WorldTransformComponent>()->worldTransform() * world;
    }

    if (m_worldTransform != world)
    {
      m_worldTransform = world;
      m_inverseWorldTransform = world.invertOrIdentity();
    }

    auto pos = m_inverseWorldTransform * m_handleSource->worldTranslation();

    auto localBounds = AABB(
        -width() * originX(),
        -height() * originY(),
        -width() * originX() + width(),
        -height() * originY() + height());

    auto local = localBounds.factorFrom(pos);
    x(local.x);
    y(local.y);
  }
}

void Joystick::apply(Artboard* artboard) const
{
  if (m_xAnimation != nullptr)
  {
    m_xAnimation->apply(
        artboard,
        ((isJoystickFlagged(JoystickFlags::invertX) ? -x() : x()) + 1.0f) /
            2.0f * m_xAnimation->durationSeconds(),
        1.0f,
        m_xAnimationInstance.get());
  }
  if (m_yAnimation != nullptr)
  {

    m_yAnimation->apply(
        artboard,
        ((isJoystickFlagged(JoystickFlags::invertY) ? -y() : y()) + 1.0f) /
            2.0f * m_yAnimation->durationSeconds(),
        1.0f,
        m_yAnimationInstance.get());
  }
  for (const auto& nestedRemapAnimation : m_dependents)
  {
    nestedRemapAnimation->advance(0, false);
  }
}

Vec2D Joystick::measureLayout(
    float width,
    LayoutMeasureMode widthMode,
    float height,
    LayoutMeasureMode heightMode)
{
  return Vec2D(
      std::min(
          (widthMode == LayoutMeasureMode::undefined
               ? std::numeric_limits<float>::max()
               : width),
          Joystick::width()),
      std::min(
          (heightMode == LayoutMeasureMode::undefined
               ? std::numeric_limits<float>::max()
               : height),
          Joystick::height()));
}

void Joystick::controlSize(
    Vec2D size,
    LayoutScaleType widthScaleType,
    LayoutScaleType heightScaleType,
    LayoutDirection direction)
{
  width(size.x);
  height(size.y);
  posX(size.x * originX());
  posY(size.y * originY());
}

void Joystick::xChanged() { artboard()->addDirt(ComponentDirt::Components); }
void Joystick::yChanged() { artboard()->addDirt(ComponentDirt::Components); }
void Joystick::posXChanged() { artboard()->addDirt(ComponentDirt::Components); }
void Joystick::posYChanged() { artboard()->addDirt(ComponentDirt::Components); }
void Joystick::widthChanged()
{
  artboard()->addDirt(ComponentDirt::Components);
}
void Joystick::heightChanged()
{
  artboard()->addDirt(ComponentDirt::Components);
}

void Joystick::addAnimationDependents(
    Artboard* artboard,
    LinearAnimation* animation)
{

  auto totalObjects = animation->numKeyedObjects();
  for (int i = 0; i < totalObjects; i++)
  {
    auto object = animation->getObject(i);
    auto coreObject = artboard->resolve(object->objectId());
    if (coreObject != nullptr && coreObject->is<NestedRemapAnimation>())
    {
      m_dependents.push_back(coreObject->as<NestedRemapAnimation>());
    }
  }
}

void Joystick::addDependents(Artboard* artboard)
{
  if (m_yAnimation != nullptr)
  {
    addAnimationDependents(artboard, m_yAnimation);
  }
  if (m_xAnimation != nullptr)
  {
    addAnimationDependents(artboard, m_xAnimation);
  }
}