#include "rive/focus_data.hpp"
#include "rive/artboard.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/artboard_host.hpp"
#include "rive/component.hpp"
#include "rive/constraints/scrolling/scroll_constraint.hpp"
#include "rive/drawable.hpp"
#include "rive/input/focusable.hpp"
#include "rive/input/focus_listener.hpp"
#include "rive/input/focus_manager.hpp"
#include "rive/layout_component.hpp"
#include "rive/math/mat2d.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/node.hpp"
#include "rive/parent_traversal.hpp"
#include "rive/semantic/semantic_data.hpp"
#include "rive/semantic/semantic_provider.hpp"
#include "rive/semantic/semantic_state.hpp"
#include "rive/text/text_input.hpp"
#include "rive/transform_component.hpp"
#include "rive/world_transform_component.hpp"
#include <algorithm>

using namespace rive;

namespace
{
SemanticData* findSiblingSemanticData(Component* self)
{
  auto* parentNode = self->parent();
  if (parentNode == nullptr || !parentNode->is<Node>())
  {
    return nullptr;
  }
  return parentNode->as<Node>()->firstChild<SemanticData>();
}
} // namespace

FocusData::~FocusData()
{
  if (m_focusNode != nullptr)
  {
    // Clear the focusable pointer first to prevent callbacks during removal
    m_focusNode->clearFocusable();

    // Take the node out of the focus tree. Its own manager pointer is the
    // normal route, but a node can end up without one (a detach that was
    // never paired with a re-add, or a manager torn down around it). Left
    // parented, such a node survives with a null focusable, which is a
    // state nothing else can clean up.
    //
    // Fall back to the nearest ancestor that still knows its manager, so
    // removal keeps clearing focus and invalidating the manager's cached
    // focusable-content answer; only when nothing in the chain is
    // registered do we settle for a plain detach.
    FocusManager* manager = m_focusNode->manager();
    if (manager == nullptr)
    {
      for (FocusNode* p = m_focusNode->parent(); p != nullptr; p = p->parent())
      {
        if (p->manager() != nullptr)
        {
          manager = p->manager();
          break;
        }
      }
    }
    if (manager != nullptr)
    {
      manager->removeChild(m_focusNode);
    }
    else
    {
      m_focusNode->removeFromParent();
    }
    // m_focusNode (rcp) is released automatically when this destructor ends
  }
}

rcp<FocusNode> FocusData::focusNode()
{
  if (m_focusNode == nullptr)
  {
    m_focusNode = rcp<FocusNode>(new FocusNode(this));
    m_focusNode->canFocus((focusFlags() & canFocusBitmask) != 0);
    m_focusNode->canTouch((focusFlags() & canTouchBitmask) != 0);
    m_focusNode->canTraverse((focusFlags() & canTraverseBitmask) != 0);
    m_focusNode->edgeBehavior(static_cast<EdgeBehavior>(m_EdgeBehaviorValue));
    m_focusNode->name(name());
    m_focusNode->capturesKeyInput(!m_captureKeyboardListeners.empty());
    // Set initial world bounds if available
    updateWorldBounds();
  }
  return m_focusNode;
}

void FocusData::addFocusListener(FocusListener* listener)
{
  m_focusListeners.push_back(listener);
}

void FocusData::removeFocusListener(FocusListener* listener)
{
  m_focusListeners.eraseAll(listener);
}

void FocusData::addKeyboardListener(KeyboardListener* listener)
{
  m_keyboardListeners.push_back(listener);
}

void FocusData::removeKeyboardListener(KeyboardListener* listener)
{
  m_keyboardListeners.eraseAll(listener);
}

void FocusData::addCaptureKeyboardListener(KeyboardListener* listener)
{
  m_captureKeyboardListeners.push_back(listener);
  if (m_focusNode != nullptr)
  {
    m_focusNode->capturesKeyInput(true);
  }
}

void FocusData::removeCaptureKeyboardListener(KeyboardListener* listener)
{
  m_captureKeyboardListeners.eraseAll(listener);
  if (m_focusNode != nullptr)
  {
    m_focusNode->capturesKeyInput(!m_captureKeyboardListeners.empty());
  }
}

void FocusData::addTextInputListener(KeyboardListener* listener)
{
  m_textInputListeners.push_back(listener);
}

void FocusData::removeTextInputListener(KeyboardListener* listener)
{
  m_textInputListeners.eraseAll(listener);
}

void FocusData::addGamepadListener(GamepadListener* listener)
{
  m_gamepadListeners.push_back(listener);
}

void FocusData::removeGamepadListener(GamepadListener* listener)
{
  m_gamepadListeners.eraseAll(listener);
}

void FocusData::focus()
{
  // Note: In C++ runtime, focus() needs a FocusManager to set focus.
  // The StateMachineInstance will handle this through its own FocusManager.
  // This method is provided for API completeness but the actual focus
  // setting happens through StateMachineInstance::setFocus(FocusData*).
}

bool FocusData::keyInput(
    Key value,
    KeyModifiers modifiers,
    bool isPressed,
    bool isRepeat)
{
  // Every listener on this node is offered the key, even once one has
  // claimed it: two listeners on the same element watching the same key
  // both run, the way they always have. A claim reports upward, where
  // FocusManager::keyInput stops the bubble -- the same split the DOM draws
  // between stopPropagation and stopImmediatePropagation.
  bool claimed = false;
  // A TextInput's own editing comes first, as the target's default
  // handling. It runs once per key however many listeners sit on the input,
  // and only when one of them opted the input into keys, as before.
  Component* target = parent();
  if (target != nullptr && target->is<TextInput>() &&
      (!m_keyboardListeners.empty() || !m_captureKeyboardListeners.empty()))
  {
    claimed = target->as<TextInput>()
                  ->keyInput(value, modifiers, isPressed, isRepeat);
  }
  for (auto* listener : m_keyboardListeners)
  {
    if (listener->keyInput(value, modifiers, isPressed, isRepeat))
    {
      claimed = true;
    }
  }
  return claimed;
}

bool FocusData::captureKeyInput(
    Key value,
    KeyModifiers modifiers,
    bool isPressed,
    bool isRepeat)
{
  // Peers again: every capture listener here runs, and one claim is enough
  // to stop the key from going any deeper or bubbling at all.
  bool claimed = false;
  for (auto* listener : m_captureKeyboardListeners)
  {
    if (listener->captureKeyInput(value, modifiers, isPressed, isRepeat))
    {
      claimed = true;
    }
  }
  return claimed;
}

bool FocusData::textInput(const std::string& text)
{

  for (auto* listener : m_textInputListeners)
  {
    if (listener->textInput(text))
    {
      return true;
    }
  }
  return false;
}

bool FocusData::selectedText(std::string& outText) const
{
  // Mirror the TextInput special case in keyInput and in
  // KeyboardListenerGroup's text routing: the focus target for a text input
  // is a FocusData child whose parent is the TextInput itself.
  Component* target = parent();
  if (target != nullptr && target->is<TextInput>())
  {
    return target->as<TextInput>()->selectedText(outText);
  }
  return false;
}

bool FocusData::acceptsTextInput() const
{
  Component* target = parent();
  return target != nullptr && target->is<TextInput>();
}

bool FocusData::blursOnOutsidePress() const
{
  Component* target = parent();
  return target != nullptr && target->is<TextInput>() &&
         target->as<TextInput>()->blursOnOutsidePress();
}

bool FocusData::hitTestFocusable(const Vec2D& rootPosition)
{
  Component* target = parent();
  if (target != nullptr && target->is<TextInput>())
  {
    return target->as<TextInput>()->hitTestFocusable(rootPosition);
  }
  return Focusable::hitTestFocusable(rootPosition);
}

bool FocusData::gamepadDispatch(
    const ListenerInvocation& invocation,
    ScriptedDrawable** outDispatchedScriptedDrawable)
{
  for (auto* listener : m_gamepadListeners)
  {
    if (listener->gamepadDispatch(invocation, outDispatchedScriptedDrawable))
    {
      return true;
    }
  }
  return false;
}

void FocusData::scrollIntoView()
{
  // Find closest LayoutComponent ancestor
  Component* layoutComponent = parent();
  while (layoutComponent != nullptr && !layoutComponent->is<LayoutComponent>())
  {
    layoutComponent = layoutComponent->parent();
  }
  if (layoutComponent == nullptr)
  {
    return;
  }

  // Get element bounds in its artboard's world space.
  // We'll transform these bounds as we cross artboard boundaries.
  AABB elementBounds = layoutComponent->as<LayoutComponent>()->worldBounds();

  // Walk up the hierarchy finding all ScrollConstraints.
  // This traversal crosses artboard boundaries via the host chain.
  ParentTraversal traversal(this);
  while (auto* p = traversal.next())
  {
    // When crossing an artboard boundary, transform element bounds from
    // nested artboard space to parent artboard space.
    if (traversal.didCrossBoundary())
    {
      auto* host = traversal.crossingHost();
      auto* sourceArtboard = traversal.sourceArtboard();
      auto* artboardInstance = sourceArtboard->is<ArtboardInstance>()
                                   ? sourceArtboard->as<ArtboardInstance>()
                                   : nullptr;
      Mat2D hostTransform = host->worldTransformForArtboard(artboardInstance);
      Vec2D min = hostTransform * Vec2D(elementBounds.minX, elementBounds.minY);
      Vec2D max = hostTransform * Vec2D(elementBounds.maxX, elementBounds.maxY);
      elementBounds = AABB(min.x, min.y, max.x, max.y);
    }

    // ScrollConstraint is a Constraint that targets Content, so we check
    // TransformComponent::constraints() to find ScrollConstraints.
    if (p->is<TransformComponent>())
    {
      auto* tc = p->as<TransformComponent>();

      for (auto* constraint : tc->constraints())
      {
        if (!constraint->is<ScrollConstraint>())
        {
          continue;
        }

        scrollConstraintToShowBounds(
            constraint->as<ScrollConstraint>(),
            elementBounds);
      }
    }
  }
}

void FocusData::scrollConstraintToShowBounds(
    ScrollConstraint* constraint,
    const AABB& elementBounds)
{
  auto* content = constraint->content();
  auto* viewport = constraint->viewport();
  if (content == nullptr || viewport == nullptr)
  {
    return;
  }

  // Get viewport position in world space.
  const Mat2D& viewportTransform = viewport->worldTransform();
  float viewportWorldX = viewportTransform[4];
  float viewportWorldY = viewportTransform[5];

  float viewportWidth = constraint->viewportWidth();
  float viewportHeight = constraint->viewportHeight();

  // Element position relative to viewport in world space.
  // This directly tells us where the element appears in the viewport.
  float viewportLeft = elementBounds.minX - viewportWorldX;
  float viewportTop = elementBounds.minY - viewportWorldY;
  float viewportRight = elementBounds.maxX - viewportWorldX;
  float viewportBottom = elementBounds.maxY - viewportWorldY;

  // Use effective scroll offset (target if animating) to handle rapid focus
  // changes.
  float effectiveScrollX = constraint->effectiveScrollOffsetX();
  float effectiveScrollY = constraint->effectiveScrollOffsetY();

  float deltaX = 0.0f;
  float deltaY = 0.0f;

  // Calculate horizontal scroll adjustment.
  if (constraint->constrainsHorizontal())
  {
    float elementWidth = viewportRight - viewportLeft;
    if (elementWidth > viewportWidth)
    {
      // Oversized element: keep the left edge visible.
      deltaX = -viewportLeft;
    }
    else if (viewportLeft < 0)
    {
      // Element is to the left of viewport, scroll right (increase
      // offset)
      deltaX = -viewportLeft;
    }
    else if (viewportRight > viewportWidth)
    {
      // Element is to the right of viewport, scroll left (decrease
      // offset)
      deltaX = -(viewportRight - viewportWidth);
    }
  }

  // Calculate vertical scroll adjustment
  if (constraint->constrainsVertical())
  {
    float elementHeight = viewportBottom - viewportTop;
    if (elementHeight > viewportHeight)
    {
      // Oversized element: keep the top edge visible.
      deltaY = -viewportTop;
    }
    else if (viewportTop < 0)
    {
      // Element is above viewport, scroll up (increase offset)
      deltaY = -viewportTop;
    }
    else if (viewportBottom > viewportHeight)
    {
      // Element is below viewport, scroll down (decrease offset)
      deltaY = -(viewportBottom - viewportHeight);
    }
  }

  // Apply scroll if needed (using animated scroll)
  if (deltaX != 0 || deltaY != 0)
  {
    // Add delta to effective scroll offset to get target position.
    Vec2D current(effectiveScrollX, effectiveScrollY);
    Vec2D target(effectiveScrollX + deltaX, effectiveScrollY + deltaY);
    Vec2D snapped = constraint->nearestSnapOffsetInDirection(current, target);
    constraint->scrollToPosition(snapped.x, snapped.y);
  }
}

void FocusData::focused()
{
  // Scroll this element into view, crossing artboard boundaries as needed
  scrollIntoView();

  // Notify listeners
  for (auto* listener : m_focusListeners)
  {
    listener->onFocused();
  }

  // Sync focus state to sibling SemanticData (if any)
  auto* sibling = findSiblingSemanticData(this);
  if (sibling != nullptr)
  {
    sibling->setFocusedState(true);
  }

  auto* parentComponent = parent();
  if (parentComponent != nullptr && parentComponent->is<TextInput>())
  {
    parentComponent->as<TextInput>()->focused();
  }
}

void FocusData::blurred()
{
  for (auto* listener : m_focusListeners)
  {
    listener->onBlurred();
  }

  // Sync focus state to sibling SemanticData (if any)
  auto* sibling = findSiblingSemanticData(this);
  if (sibling != nullptr)
  {
    sibling->setFocusedState(false);
  }

  auto* parentComponent = parent();
  if (parentComponent != nullptr && parentComponent->is<TextInput>())
  {
    parentComponent->as<TextInput>()->blurred();
  }
}

void FocusData::focusFlagsChanged()
{
  if (m_focusNode != nullptr)
  {
    m_focusNode->canFocus((focusFlags() & canFocusBitmask) != 0);
    m_focusNode->canTouch((focusFlags() & canTouchBitmask) != 0);
    m_focusNode->canTraverse((focusFlags() & canTraverseBitmask) != 0);
  }
}

void FocusData::edgeBehaviorValueChanged()
{
  if (m_focusNode != nullptr)
  {
    m_focusNode->edgeBehavior(static_cast<EdgeBehavior>(m_EdgeBehaviorValue));
  }
}

FocusData* FocusData::findParentFocusData() const
{
  // FocusData's parent is typically a Node. Walk up from the parent
  // to find any ancestor Node that has a FocusData child.
  auto* current = parent();
  while (current != nullptr)
  {
    if (current->is<Node>())
    {
      auto* node = current->as<Node>();
      for (auto* child : node->children())
      {
        if (child->is<FocusData>() && child != this)
        {
          return child->as<FocusData>();
        }
      }
    }
    current = current->parent();
  }
  return nullptr;
}

rcp<FocusNode> FocusData::findClosestFocusNode(Component* component)
{
  if (component == nullptr)
  {
    return nullptr;
  }

  auto* current = component->parent();
  while (current != nullptr)
  {
    // Check if we've hit an artboard boundary
    if (current->is<Artboard>())
    {
      auto* artboard = current->as<Artboard>();
      // Try to cross the artboard boundary via the host component
      auto* host = artboard->host();
      if (host != nullptr)
      {
        auto* hostComponent = host->hostComponent();
        if (hostComponent != nullptr && hostComponent->is<ContainerComponent>())
        {
          // Continue searching from the host component (e.g.,
          // NestedArtboard)
          current = hostComponent->as<ContainerComponent>();
          continue;
        }
      }
#ifdef WITH_RIVE_TOOLS
      // Fall back to externally-set parent focus node (editor scenario)
      auto externalNode = artboard->externalParentFocusNode();
      if (externalNode != nullptr)
      {
        return externalNode;
      }
#endif
      // No way to traverse up, stop searching
      return nullptr;
    }

    // Check if this node has a FocusData child
    if (current->is<Node>())
    {
      for (auto* child : current->as<Node>()->children())
      {
        if (child->is<FocusData>())
        {
          return child->as<FocusData>()->focusNode();
        }
      }
    }

    current = current->parent();
  }
  return nullptr;
}

namespace
{

bool componentAllowsFocusTraversal(const Component* c)
{
  if (c == nullptr || c->isCollapsed())
  {
    return false;
  }
  if (c->is<Drawable>())
  {
    if (c->as<Drawable>()->isHidden())
    {
      return false;
    }
  }
  if (c->is<TransformComponent>())
  {
    if (c->as<TransformComponent>()->renderOpacity() <= 0.0f)
    {
      return false;
    }
  }
  return true;
}

} // namespace

bool FocusData::isEligibleForFocusTraversal() const
{
  if (isCollapsed())
  {
    return false;
  }
  Component* start = parent();
  if (start == nullptr)
  {
    return true;
  }
  if (!componentAllowsFocusTraversal(start))
  {
    return false;
  }
  ParentTraversal traversal(start);
  while (true)
  {
    ContainerComponent* p = traversal.next();
    if (p == nullptr)
    {
      break;
    }
    if (!componentAllowsFocusTraversal(p))
    {
      return false;
    }
    if (traversal.didCrossBoundary())
    {
      ArtboardHost* host = traversal.crossingHost();
      if (host != nullptr)
      {
        Component* hc = host->hostComponent();
        if (hc != nullptr)
        {
          if (!componentAllowsFocusTraversal(hc))
          {
            return false;
          }
          if (hc->is<NestedArtboard>() && hc->as<NestedArtboard>()->isPaused())
          {
            return false;
          }
        }
      }
    }
  }
  return true;
}

bool FocusData::worldPosition(Vec2D& outPosition)
{
  // Get local position from parent transform component
  auto* parentComponent = parent();
  if (!parentComponent || !parentComponent->is<WorldTransformComponent>())
  {
    return false;
  }
  Vec2D localPos = parentComponent->as<WorldTransformComponent>()
                       ->worldTranslation();

  // Transform to root artboard space (handles nested artboards)
  auto* ab = artboard();
  if (ab)
  {
    outPosition = ab->rootTransform(localPos);
  }
  else
  {
    outPosition = localPos;
  }
  return true;
}

void FocusData::nameChanged()
{
  if (m_focusNode != nullptr)
  {
    m_focusNode->name(name());
  }
}

void FocusData::buildDependencies()
{
  Super::buildDependencies();
  // Depend on parent's world transform so we update when it moves
  auto* parentComponent = parent();
  if (parentComponent != nullptr)
  {
    parentComponent->addDependent(this);
  }
}

void FocusData::update(ComponentDirt value)
{
  if ((value & ComponentDirt::WorldTransform) == ComponentDirt::WorldTransform)
  {
    updateWorldBounds();
  }
}

bool FocusData::worldBounds(AABB& outBounds)
{
  auto* parentComponent = parent();
  if (parentComponent == nullptr || !parentComponent->is<LayoutComponent>())
  {
    return false;
  }
  AABB bounds = parentComponent->as<LayoutComponent>()->worldBounds();
  // Transform to root artboard space (handles nested artboards); all four
  // corners so rotated/skewed hosts still yield a valid AABB.
  auto* ab = artboard();
  if (ab != nullptr)
  {
    bounds = SemanticProvider::rootTransformAABB(ab, bounds);
  }
  outBounds = bounds;
  return true;
}

void FocusData::updateWorldBounds()
{
  if (m_focusNode == nullptr)
  {
    return;
  }

  AABB bounds;
  if (worldBounds(bounds))
  {
    m_focusNode->worldBounds(bounds);
  }
  else
  {
    m_focusNode->clearWorldBounds();
  }
}