/*
 * Copyright 2024 Rive
 */

#include "rive/input/focus_manager.hpp"
#include "rive/artboard.hpp"
#include "rive/artboard_host.hpp"
#include "rive/animation/listener_invocation.hpp"
#include "rive/focus_data.hpp"
#include "rive/input/focusable.hpp"
#include "rive/math/aabb.hpp"
#include <algorithm>
#include <cstddef>
#include <cmath>
#include <limits>
#include <unordered_set>

namespace rive
{

static bool focusNodeEligibleForFocus(FocusNode* node)
{
  if (node == nullptr || !node->canFocus())
  {
    return false;
  }
#ifdef WITH_RIVE_TOOLS
  if (node->isCollapsed())
  {
    return false;
  }
#endif
  Focusable* f = node->focusable();
  if (f == nullptr)
  {
    // A node that never had a Focusable is externally managed — a
    // structural scope, or a target a host created through the FocusNode
    // API. There is nothing to ask about visibility, so treat it as
    // eligible, as before.
    //
    // A node that HAD one and lost it is defunct: ~FocusData clears the
    // backing when the FocusData dies. Such a node must not stay a focus
    // stop. Nothing is left that could ever report it collapsed or hidden,
    // so it would be permanently eligible — and, being unreachable through
    // its own FocusData, unremovable. Traversal still descends *through*
    // it, as it does through any non-stop, so live children stay
    // reachable.
    return !node->hadFocusable();
  }
  return f->isEligibleForFocusTraversal();
}

// A focus stop is any node navigation may land on: it opts into traversal, it
// can hold focus, and it is currently visible. Being a stop says nothing about
// whether the node has children — a container that is itself focusable and
// traversable is a stop AND a scope, and the walk visits it before its
// children.
static bool isFocusStop(FocusNode* node)
{
  if (node == nullptr || !node->canTraverse())
  {
    return false;
  }
  return focusNodeEligibleForFocus(node);
}

// `children` in traversal order. Stable, so equal tabIndex keeps hierarchy
// order. Deliberately unfiltered: the walk decides per subtree whether
// anything in it is reachable, and filtering here would answer that question a
// second time for every child it then descends into.
static std::vector<FocusNode*> sortedByTabIndex(
    const std::vector<rcp<FocusNode>>& children)
{
  std::vector<FocusNode*> result;
  result.reserve(children.size());
  for (const auto& child : children)
  {
    result.push_back(child.get());
  }
  std::stable_sort(
      result.begin(),
      result.end(),
      [](FocusNode* a, FocusNode* b) { return a->tabIndex() < b->tabIndex(); });
  return result;
}

// The first stop in `node`'s subtree in pre-order: `node` itself when it is a
// stop, else the first stop under its children in tab order. Null when the
// subtree holds none.
//
// Nothing is pruned on the way down. A node that is not a stop — a structural
// scope, an authored canFocus=false container, a node whose FocusData died —
// still has its children visited, so a parent's own flags never decide for its
// children.
static FocusNode* firstStopInSubtree(FocusNode* node)
{
  if (node == nullptr)
  {
    return nullptr;
  }
  if (isFocusStop(node))
  {
    return node;
  }
  for (FocusNode* child : sortedByTabIndex(node->children()))
  {
    FocusNode* stop = firstStopInSubtree(child);
    if (stop != nullptr)
    {
      return stop;
    }
  }
  return nullptr;
}

// Mirror of firstStopInSubtree: the last stop in reverse pre-order, so
// children (reverse tab order) come before `node` itself.
static FocusNode* lastStopInSubtree(FocusNode* node)
{
  if (node == nullptr)
  {
    return nullptr;
  }
  auto children = sortedByTabIndex(node->children());
  for (auto it = children.rbegin(); it != children.rend(); ++it)
  {
    FocusNode* stop = lastStopInSubtree(*it);
    if (stop != nullptr)
    {
      return stop;
    }
  }
  return isFocusStop(node) ? node : nullptr;
}

static FocusNode* firstStopAmong(const std::vector<FocusNode*>& siblings)
{
  for (FocusNode* sibling : siblings)
  {
    FocusNode* stop = firstStopInSubtree(sibling);
    if (stop != nullptr)
    {
      return stop;
    }
  }
  return nullptr;
}

static FocusNode* lastStopAmong(const std::vector<FocusNode*>& siblings)
{
  for (auto it = siblings.rbegin(); it != siblings.rend(); ++it)
  {
    FocusNode* stop = lastStopInSubtree(*it);
    if (stop != nullptr)
    {
      return stop;
    }
  }
  return nullptr;
}

// The root artboard whose tree `node` sits in, or nullptr when it can't be
// attributed to one. Walks up the focus tree to the nearest node backed by a
// Focusable — a structural scope has no artboard of its own, but something
// above it does — then up the nested-artboard chain, matching
// StateMachineInstance::rootArtboard so the two agree on what "root" means.
static const Artboard* focusRootArtboard(FocusNode* node)
{
  Artboard* artboard = nullptr;
  for (FocusNode* n = node; n != nullptr && artboard == nullptr;
       n = n->parent())
  {
    if (n->focusable() != nullptr)
    {
      artboard = n->focusable()->focusableArtboard();
    }
  }
  if (artboard == nullptr)
  {
    return nullptr;
  }
  while (artboard->host() != nullptr &&
         artboard->host()->parentArtboard() != nullptr)
  {
    artboard = artboard->host()->parentArtboard();
  }
  return artboard;
}

// True when `node` belongs to a root OTHER than the one whose update pass just
// ran, and so has to wait for its own. A node no artboard backs — one a host
// created through the FocusNode API — belongs to no root and is never
// deferred: no root's pass would ever claim it, so deferring would mean never.
static bool belongsToAnotherRoot(FocusNode* node, const Artboard* rootArtboard)
{
  const Artboard* root = focusRootArtboard(node);
  return root != nullptr && root != rootArtboard;
}

void FocusManager::dropFocusIfFocusTargetHidden()
{
  // Tested for FOCUS, not for traversal. canTraverse only means "not in
  // navigation"; a node a script, a pointer or a FocusAction focused keeps
  // that focus while it is visible, even though Tab would never pick it.
  if (m_primaryFocus == nullptr ||
      focusNodeEligibleForFocus(m_primaryFocus.get()))
  {
    return;
  }

  // Walk ancestors outward and take the first that can still offer a focus
  // stop. Children first, the ancestor itself only as a fallback: plain
  // pre-order would hand back the ancestor whenever it is a stop, and focus
  // should keep its depth — a hidden list row hands over to a sibling row,
  // not to the list.
  for (FocusNode* ancestor = m_primaryFocus->parent(); ancestor != nullptr;
       ancestor = ancestor->parent())
  {
    FocusNode* stop = firstStopAmong(sortedByTabIndex(ancestor->children()));
    if (stop == nullptr && isFocusStop(ancestor))
    {
      stop = ancestor;
    }
    if (stop != nullptr)
    {
      setFocus(ref_rcp(stop));
      return;
    }
  }
  clearFocus();
}

void FocusManager::dropFocusIfFocusTargetHidden(const Artboard* rootArtboard)
{
  // Scoped for the same reason as processPendingFocusRequests: whether the
  // target still counts as visible is read from renderOpacity and collapse,
  // and only its own root's update pass has refreshed those. Testing the
  // target itself is the right question here — unlike the descent below,
  // this is a claim about where focus already sits.
  if (m_primaryFocus == nullptr ||
      belongsToAnotherRoot(m_primaryFocus.get(), rootArtboard))
  {
    return;
  }
  dropFocusIfFocusTargetHidden();
}

Artboard* FocusManager::primaryFocusArtboard() const
{
  if (m_primaryFocus == nullptr || m_primaryFocus->focusable() == nullptr)
  {
    return nullptr;
  }

  // Get the immediate artboard containing the focused element
  Artboard* artboard = m_primaryFocus->focusable()->focusableArtboard();
  if (artboard == nullptr)
  {
    return nullptr;
  }

  // Walk up the nested artboard chain to find the root (one with no host)
  // The root artboard is the one mounted by Dart, which has no host.
  while (artboard->host() != nullptr &&
         artboard->host()->parentArtboard() != nullptr)
  {
    artboard = artboard->host()->parentArtboard();
  }

  return artboard;
}

FocusManager::~FocusManager()
{
  // Don't call clearFocus() here - it would invoke callbacks on FocusNodes,
  // but during destruction (especially Dart finalizers) callbacks may be
  // invalid. Just clear the reference directly.
  for (auto node : m_rootNodes)
  {
    removeManager(node);
  }
  m_primaryFocus = nullptr;
}

void FocusManager::removeManager(rcp<FocusNode> node)
{
  for (const auto& child : node->children())
  {
    removeManager(child);
  }
  node->m_manager = nullptr;
}

// Counterpart to removeManager: a node joining this manager brings its whole
// subtree with it, so every descendant's manager pointer has to be restored
// too — not just the node handed to addChild.
//
// Without this, a detach/re-add cycle leaves descendants pointing at no
// manager.
void FocusManager::assignManager(rcp<FocusNode> node)
{
  for (const auto& child : node->children())
  {
    assignManager(child);
  }
  node->m_manager = this;
}

void FocusManager::setFocus(rcp<FocusNode> node)
{
  // Focus lands exactly where it was asked to. There is no descent: a node
  // that can be focused is focused, children or not, and a node that cannot
  // (canFocus==false, collapsed, hidden, opacity 0, a defunct FocusData) is
  // a no-op rather than a redirect to some descendant the caller never
  // named. focusNodeEligibleForFocus already covers canFocus.
  if (node != nullptr && !focusNodeEligibleForFocus(node.get()))
  {
    return;
  }

  if (node == m_primaryFocus)
  {
    return;
  }

  FocusNode* oldFocus = m_primaryFocus.get();
  m_primaryFocus = std::move(node);
  notifyFocusChange(oldFocus, m_primaryFocus.get());
}

void FocusManager::enqueueFocusRequest(PendingFocusRequest request)
{
  if (m_pendingFocusRequests.size() >= maxPendingFocusRequests)
  {
    m_pendingFocusRequests.erase(m_pendingFocusRequests.begin());
  }
  m_pendingFocusRequests.push_back(std::move(request));
}

bool FocusManager::hasPendingFocusRequests(const Artboard* rootArtboard) const
{
  for (const auto& request : m_pendingFocusRequests)
  {
    if (request.rootArtboard == rootArtboard)
    {
      return true;
    }
  }
  return false;
}

bool FocusManager::applyFocusTraversal(uint32_t traversalKind)
{
  switch (traversalKind)
  {
    case 1:
      return focusPrevious();
    case 2:
      return focusUp();
    case 3:
      return focusDown();
    case 4:
      return focusLeft();
    case 5:
      return focusRight();
    case 0:
    default:
      return focusNext();
  }
}

void FocusManager::requestFocus(
    rcp<FocusNode> node,
    const Artboard* rootArtboard)
{
  if (node == nullptr)
  {
    return;
  }
  // Try now: when the target is already focusable this lands on the frame it
  // was asked for, which is what pointer- and script-driven focus expect.
  // Only a failed attempt is deferred, and a failed attempt is a true no-op
  // (setFocus rejects an ineligible node before touching primary focus), so
  // trying costs nothing. Skipped while requests are already pending for
  // this root, so a queued request can't be overtaken by a later one.
  if (!hasPendingFocusRequests(rootArtboard))
  {
    setFocus(node);
    if (hasFocus(node))
    {
      return;
    }
  }
  enqueueFocusRequest(
      {PendingFocusRequest::Kind::target, std::move(node), 0, rootArtboard});
}

void FocusManager::requestClearFocus(const Artboard* rootArtboard)
{
  // Clearing can't be blocked by stale components, so it never needs to be
  // retried — it only queues to stay behind requests already pending.
  if (!hasPendingFocusRequests(rootArtboard))
  {
    clearFocus();
    return;
  }
  enqueueFocusRequest(
      {PendingFocusRequest::Kind::clear, nullptr, 0, rootArtboard});
}

void FocusManager::requestTraversal(
    uint32_t traversalKind,
    const Artboard* rootArtboard)
{
  if (!hasPendingFocusRequests(rootArtboard) &&
      applyFocusTraversal(traversalKind))
  {
    return;
  }
  enqueueFocusRequest(
      {PendingFocusRequest::Kind::traverse,
       nullptr,
       traversalKind,
       rootArtboard});
}

bool FocusManager::applyPendingFocusRequest(const PendingFocusRequest& request)
{
  switch (request.kind)
  {
    case PendingFocusRequest::Kind::target:
      // A FocusData destroyed between queueing and draining clears its
      // node's focusable. Report that as done, not as "didn't take":
      // the target is gone, so retrying would never help.
      if (request.node == nullptr || request.node->focusable() == nullptr)
      {
        return true;
      }
      setFocus(request.node);
      return hasFocus(request.node);
    case PendingFocusRequest::Kind::clear:
      clearFocus();
      return true;
    case PendingFocusRequest::Kind::traverse:
      return applyFocusTraversal(request.traversalKind);
  }
  return true;
}

void FocusManager::processPendingFocusRequests(const Artboard* rootArtboard)
{
  drainPendingFocusRequests(
      rootArtboard,
      /*keepUnapplied=*/true,
      /*allRoots=*/false);
}

void FocusManager::processAllPendingFocusRequests()
{
  drainPendingFocusRequests(
      nullptr,
      /*keepUnapplied=*/true,
      /*allRoots=*/true);
}

void FocusManager::finishPendingFocusRequests(const Artboard* rootArtboard)
{
  drainPendingFocusRequests(
      rootArtboard,
      /*keepUnapplied=*/false,
      /*allRoots=*/false);
}

void FocusManager::finishAllPendingFocusRequests()
{
  drainPendingFocusRequests(
      nullptr,
      /*keepUnapplied=*/false,
      /*allRoots=*/true);
}

void FocusManager::drainPendingFocusRequests(
    const Artboard* rootArtboard,
    bool keepUnapplied,
    bool allRoots)
{
  if (m_pendingFocusRequests.empty())
  {
    return;
  }

  // Applying a request notifies focus/blur listeners, which can queue more
  // work, so move the pending list out before draining it. Requests from
  // other roots go back on the queue for their own root to drain.
  //
  // Everything put back goes through enqueueFocusRequest, not a bare
  // push_back: a listener firing mid-drain can enqueue alongside us, so the
  // queue has to stay under its cap here too.
  auto requests = std::move(m_pendingFocusRequests);
  m_pendingFocusRequests.clear();

  for (auto& request : requests)
  {
    if (!allRoots && request.rootArtboard != rootArtboard)
    {
      enqueueFocusRequest(std::move(request));
      continue;
    }
    if (!applyPendingFocusRequest(request) && keepUnapplied)
    {
      enqueueFocusRequest(std::move(request));
    }
  }
}

void FocusManager::clearFocus()
{
  if (m_primaryFocus)
  {
    // Move to local variable to keep node alive during notification.
    // Setting m_primaryFocus to nullptr first ensures hasFocus() returns
    // false during the blurred() callback, but the node stays alive until
    // notification completes.
    auto oldFocus = std::move(m_primaryFocus);
    notifyFocusChange(oldFocus.get(), nullptr);
    // oldFocus is released here after notification is complete
  }
}

bool FocusManager::hasFocus(rcp<FocusNode> node) const
{
  // The hasFocus flag on the node is maintained by notifyFocusChange
  return node && node->hasFocus();
}

bool FocusManager::hasPrimaryFocus(rcp<FocusNode> node) const
{
  return m_primaryFocus == node;
}

void FocusManager::addChild(rcp<FocusNode> parent, rcp<FocusNode> child)
{
  if (!child)
  {
    return;
  }

  size_t index = parent ? parent->children().size() : m_rootNodes.size();
  addChild(std::move(parent), std::move(child), index);
}

void FocusManager::addChild(
    rcp<FocusNode> parent,
    rcp<FocusNode> child,
    size_t index)
{
  if (!child)
  {
    return;
  }
  // The child (and its subtree) joins this manager; root insertions below
  // don't pass through FocusNode::insertChild, so invalidate here.
  markFocusableContentDirty();
  if (child->parent())
  {
    child->removeFromParent();
  }
  else if (child->m_manager != nullptr && child->m_manager != this)
  {
    // The child is a root of a DIFFERENT manager (e.g. a scope migrating
    // from a nested state machine's internal manager to the parent). Erase
    // it from that manager's root list so it belongs to exactly one
    // manager.
    child->m_manager->eraseRoot(child);
  }
  else
  {
    eraseRoot(child);
  }
  // The whole subtree joins this manager, not just `child`.
  assignManager(child);
  if (parent)
  {
    parent->insertChild(index, std::move(child));
  }
  else
  {
    if (index > m_rootNodes.size())
    {
      index = m_rootNodes.size();
    }
    m_rootNodes.insert(
        m_rootNodes.begin() + static_cast<ptrdiff_t>(index),
        std::move(child));
  }
}

void FocusManager::removeChild(rcp<FocusNode> child)
{
  if (!child)
  {
    return;
  }

  // Clear focus if this node or descendant has focus
  if (hasFocus(child))
  {
    clearFocus();
  }

  detachChild(std::move(child));
}

void FocusManager::detachChild(rcp<FocusNode> child)
{
  if (!child)
  {
    return;
  }
  // Usually redundant with the parent-side notification in
  // removeFromParent() / eraseRoot(), but load-bearing when the detached
  // node's parent isn't manager-attached (m_manager == nullptr), where
  // neither downstream mark can fire.
  markFocusableContentDirty();

  // Removing a node takes its whole subtree out of the manager, so clear
  // m_manager on every descendant too: a descendant held elsewhere (e.g. a
  // persistent NestedArtboard scope) must not retain a pointer to a manager
  // it no longer belongs to.
  removeManager(child);

  // NOTE: unlike removeChild, this intentionally does NOT clear focus. The
  // node stays alive (held by m_primaryFocus and the caller) and its
  // hasFocus flag survives, so reordering an existing node preserves focus
  // and fires no blur/focus callbacks. A genuinely re-parented focused node
  // keeps its hasFocus flag but its new ancestors won't carry it; that only
  // affects notifyFocusChange's blur-walk on a later focus change, not input
  // bubbling (which walks parent() directly).

  // Clear the manager reference
  child->m_manager = nullptr;

  if (child->parent())
  {
    child->removeFromParent();
  }
  else
  {
    eraseRoot(child);
  }
}

void FocusManager::eraseRoot(const rcp<FocusNode>& node)
{
  auto it = std::find(m_rootNodes.begin(), m_rootNodes.end(), node);
  if (it != m_rootNodes.end())
  {
    m_rootNodes.erase(it);
    // Covers root removal on THIS manager even when reached from another
    // manager's addChild (scope migration between managers).
    markFocusableContentDirty();
  }
}

namespace
{
// Raises the manager's traversing flag for the focus changes made inside one
// traversal call. Restores the previous value so a traversal started from a
// focus callback leaves the outer one flagged.
class TraversalScope
{
public:
  TraversalScope(bool& traversing)
      : m_traversing(traversing)
      , m_previous(traversing)
  {
    m_traversing = true;
  }
  ~TraversalScope() { m_traversing = m_previous; }

private:
  bool& m_traversing;
  bool m_previous;
};
} // namespace

bool FocusManager::focusNext()
{
  dropFocusIfFocusTargetHidden();
  TraversalScope traversal(m_traversing);
  return findNextFocusable(m_primaryFocus.get(), true) != nullptr;
}

bool FocusManager::focusPrevious()
{
  dropFocusIfFocusTargetHidden();
  TraversalScope traversal(m_traversing);
  return findNextFocusable(m_primaryFocus.get(), false) != nullptr;
}

// Root-space world position from FocusNode. Live focusable geometry first;
// the node's cached bounds go stale when an ancestor host moves the
// containing artboard instance, and remain only for externally-managed nodes.
static bool getRootPosition(FocusNode* node, Vec2D& outPosition)
{
  if (!node)
  {
    return false;
  }
  if (node->focusable())
  {
    AABB bounds;
    if (node->focusable()->worldBounds(bounds))
    {
      outPosition = bounds.center();
      return true;
    }
    if (node->focusable()->worldPosition(outPosition))
    {
      return true;
    }
  }
  if (node->hasWorldBounds())
  {
    outPosition = node->worldBounds().center();
    return true;
  }
  return false;
}

// Root-space world bounds from FocusNode; same live-first policy as
// getRootPosition.
static bool getRootBounds(FocusNode* node, AABB& outBounds)
{
  if (!node)
  {
    return false;
  }
  if (node->focusable() && node->focusable()->worldBounds(outBounds))
  {
    return true;
  }
  if (node->hasWorldBounds())
  {
    outBounds = node->worldBounds();
    return true;
  }
  return false;
}

// Every focus stop in the tree, in hierarchy order. Unlike Tab this ignores
// structure entirely — scoring is purely spatial — but it must agree with Tab
// on WHAT a stop is, so a container that is itself focusable and traversable
// is a candidate like any other.
static void collectFocusStops(
    const std::vector<rcp<FocusNode>>& nodes,
    std::vector<FocusNode*>& result)
{
  for (const auto& node : nodes)
  {
    if (isFocusStop(node.get()))
    {
      result.push_back(node.get());
    }
    collectFocusStops(node->children(), result);
  }
}

static bool subtreeHasFocusableContent(const std::vector<rcp<FocusNode>>& nodes)
{
  for (const auto& node : nodes)
  {
    // A node backed by focusable data counts even while it is currently
    // ineligible for traversal: eligibility (collapse, hidden ancestors)
    // and canFocus/canTraverse are runtime state that can change on any
    // frame, while this signal gates one-time setup in high-level
    // runtimes (e.g. attaching tab/shift+tab listeners in JS). Unbacked
    // nodes with canFocus=false are structural scopes and don't count on
    // their own.
    if (node->focusable() != nullptr || node->canFocus())
    {
      return true;
    }
    if (subtreeHasFocusableContent(node->children()))
    {
      return true;
    }
  }
  return false;
}

bool FocusManager::hasFocusableContent() const
{
  if (m_focusableContentDirty)
  {
    m_hasFocusableContent = subtreeHasFocusableContent(m_rootNodes);
    m_focusableContentDirty = false;
  }
  return m_hasFocusableContent;
}

// Calculate overlap on the orthogonal axis (perpendicular to navigation)
// Returns the length of overlap, or 0 if no overlap
static float calculateOverlap(float aMin, float aMax, float bMin, float bMax)
{
  float overlapMin = std::max(aMin, bMin);
  float overlapMax = std::min(aMax, bMax);
  return std::max(0.0f, overlapMax - overlapMin);
}

// CSS Spatial Navigation-inspired scoring for bounds-aware navigation
// Formula: distance = displacement + orthogonalWeight * orthogonalDistance -
// sqrt(overlap)
struct ScoreBreakdown
{
  float displacement;
  float orthogonalDistance;
  float overlap;
  float orthogonalWeight;
  float total;
  bool rejected;
};

static ScoreBreakdown scoreCandidateBoundsDetailed(
    const AABB& current,
    const AABB& candidate,
    Direction direction)
{
  // CSS Spatial Navigation weights
  const float horizontalWeight = 30.0f;
  const float verticalWeight = 2.0f;

  ScoreBreakdown result = {};

  switch (direction)
  {
    case Direction::left:
      // Displacement: distance from current's left edge to candidate's
      // right edge
      result.displacement = current.left() - candidate.right();
      if (result.displacement < 0)
      {
        result.rejected = true;
        result.total = std::numeric_limits<float>::max();
        return result;
      }
      // Orthogonal: vertical distance between closest edges
      result.orthogonalDistance = std::max(
          0.0f,
          std::max(
              candidate.top() - current.bottom(),
              current.top() - candidate.bottom()));
      result.overlap = calculateOverlap(
          current.top(),
          current.bottom(),
          candidate.top(),
          candidate.bottom());
      result.orthogonalWeight = horizontalWeight;
      break;

    case Direction::right:
      result.displacement = candidate.left() - current.right();
      if (result.displacement < 0)
      {
        result.rejected = true;
        result.total = std::numeric_limits<float>::max();
        return result;
      }
      result.orthogonalDistance = std::max(
          0.0f,
          std::max(
              candidate.top() - current.bottom(),
              current.top() - candidate.bottom()));
      result.overlap = calculateOverlap(
          current.top(),
          current.bottom(),
          candidate.top(),
          candidate.bottom());
      result.orthogonalWeight = horizontalWeight;
      break;

    case Direction::up:
      result.displacement = current.top() - candidate.bottom();
      if (result.displacement < 0)
      {
        result.rejected = true;
        result.total = std::numeric_limits<float>::max();
        return result;
      }
      result.orthogonalDistance = std::max(
          0.0f,
          std::max(
              candidate.left() - current.right(),
              current.left() - candidate.right()));
      result.overlap = calculateOverlap(
          current.left(),
          current.right(),
          candidate.left(),
          candidate.right());
      result.orthogonalWeight = verticalWeight;
      break;

    case Direction::down:
      result.displacement = candidate.top() - current.bottom();
      if (result.displacement < 0)
      {
        result.rejected = true;
        result.total = std::numeric_limits<float>::max();
        return result;
      }
      result.orthogonalDistance = std::max(
          0.0f,
          std::max(
              candidate.left() - current.right(),
              current.left() - candidate.right()));
      result.overlap = calculateOverlap(
          current.left(),
          current.right(),
          candidate.left(),
          candidate.right());
      result.orthogonalWeight = verticalWeight;
      break;
  }

  // CSS-inspired formula: displacement + weighted orthogonal - sqrt(overlap)
  // The sqrt(overlap) bonus favors candidates that are "in line" with current
  result.total = result.displacement +
                 result.orthogonalWeight * result.orthogonalDistance -
                 std::sqrt(result.overlap);
  return result;
}

static float scoreCandidateBounds(
    const AABB& current,
    const AABB& candidate,
    Direction direction)
{
  return scoreCandidateBoundsDetailed(current, candidate, direction).total;
}

// Point-based scoring fallback for nodes without bounds
static float scoreCandidatePoint(
    const Vec2D& currentPos,
    const Vec2D& candidatePos,
    Direction direction)
{
  const float horizontalWeight = 30.0f;
  const float verticalWeight = 2.0f;

  Vec2D delta = candidatePos - currentPos;
  float primary, orthogonal, orthogonalWeight;

  switch (direction)
  {
    case Direction::left:
      primary = -delta.x;
      orthogonal = std::abs(delta.y);
      orthogonalWeight = horizontalWeight;
      break;
    case Direction::right:
      primary = delta.x;
      orthogonal = std::abs(delta.y);
      orthogonalWeight = horizontalWeight;
      break;
    case Direction::up:
      primary = -delta.y;
      orthogonal = std::abs(delta.x);
      orthogonalWeight = verticalWeight;
      break;
    case Direction::down:
      primary = delta.y;
      orthogonal = std::abs(delta.x);
      orthogonalWeight = verticalWeight;
      break;
  }

  if (primary <= 0)
  {
    return std::numeric_limits<float>::max();
  }

  return primary + orthogonalWeight * orthogonal;
}

FocusNode* FocusManager::findNodeInDirection(
    FocusNode* current,
    Direction direction) const
{
  if (!current)
  {
    return nullptr;
  }

  std::vector<FocusNode*> candidates;
  collectFocusStops(m_rootNodes, candidates);

  FocusNode* best = nullptr;
  float bestScore = std::numeric_limits<float>::max();

  // Try to get bounds for current node
  AABB currentBounds;
  bool currentHasBounds = getRootBounds(current, currentBounds);

  // Fallback to position if no bounds
  Vec2D currentPos;
  if (!currentHasBounds && !getRootPosition(current, currentPos))
  {
    return nullptr;
  }

  for (FocusNode* candidate : candidates)
  {
    if (candidate == current)
    {
      continue;
    }

    float score;

    // Try bounds-based scoring first
    AABB candidateBounds;
    if (currentHasBounds && getRootBounds(candidate, candidateBounds))
    {
      score = scoreCandidateBounds(currentBounds, candidateBounds, direction);
    }
    else
    {
      // Fall back to point-based scoring
      Vec2D candidatePos;
      if (!getRootPosition(candidate, candidatePos))
      {
        continue;
      }

      if (currentHasBounds)
      {
        // Use center of current bounds
        score = scoreCandidatePoint(
            currentBounds.center(),
            candidatePos,
            direction);
      }
      else
      {
        score = scoreCandidatePoint(currentPos, candidatePos, direction);
      }
    }

    if (score < bestScore)
    {
      bestScore = score;
      best = candidate;
    }
  }

  return best;
}

bool FocusManager::focusLeft()
{
  dropFocusIfFocusTargetHidden();
  TraversalScope traversal(m_traversing);
  FocusNode* next = findNodeInDirection(m_primaryFocus.get(), Direction::left);
  if (next)
  {
    setFocus(ref_rcp(next));
    return true;
  }
  return false;
}

bool FocusManager::focusRight()
{
  dropFocusIfFocusTargetHidden();
  TraversalScope traversal(m_traversing);
  FocusNode* next = findNodeInDirection(m_primaryFocus.get(), Direction::right);
  if (next)
  {
    setFocus(ref_rcp(next));
    return true;
  }
  return false;
}

bool FocusManager::focusUp()
{
  dropFocusIfFocusTargetHidden();
  TraversalScope traversal(m_traversing);
  FocusNode* next = findNodeInDirection(m_primaryFocus.get(), Direction::up);
  if (next)
  {
    setFocus(ref_rcp(next));
    return true;
  }
  return false;
}

bool FocusManager::focusDown()
{
  dropFocusIfFocusTargetHidden();
  TraversalScope traversal(m_traversing);
  FocusNode* next = findNodeInDirection(m_primaryFocus.get(), Direction::down);
  if (next)
  {
    setFocus(ref_rcp(next));
    return true;
  }
  return false;
}

bool FocusManager::keyInput(
    Key key,
    KeyModifiers modifiers,
    bool isPressed,
    bool isRepeat)
{
  dropFocusIfFocusTargetHidden();
  if (captureKeyInput(key, modifiers, isPressed, isRepeat))
  {
    return true;
  }
  // Bubble up through focus tree until someone handles the input
  FocusNode* node = m_primaryFocus.get();
  while (node != nullptr)
  {
    if (node->keyInput(key, modifiers, isPressed, isRepeat))
    {
      return true;
    }
    node = node->parent();
  }
  return false;
}

bool FocusManager::captureKeyInput(
    Key key,
    KeyModifiers modifiers,
    bool isPressed,
    bool isRepeat)
{
  // Most trees have nothing in the capture phase, and for them this walk
  // only reads one flag per ancestor.
  FocusNode* node = m_primaryFocus.get();
  while (node != nullptr && !node->capturesKeyInput())
  {
    node = node->parent();
  }
  if (node == nullptr)
  {
    return false;
  }
  // The capture phase runs outermost first, so collect the nodes that take
  // part and walk them back down. Held by reference: a listener's actions
  // can tear down part of the tree before the walk reaches it.
  std::vector<rcp<FocusNode>> path;
  for (; node != nullptr; node = node->parent())
  {
    if (node->capturesKeyInput())
    {
      path.push_back(ref_rcp(node));
    }
  }
  for (auto itr = path.rbegin(); itr != path.rend(); ++itr)
  {
    if ((*itr)->captureKeyInput(key, modifiers, isPressed, isRepeat))
    {
      return true;
    }
  }
  return false;
}

bool FocusManager::textInput(const std::string& text)
{
  dropFocusIfFocusTargetHidden();
  // Bubble up through focus tree until someone handles the input
  FocusNode* node = m_primaryFocus.get();
  while (node != nullptr)
  {
    if (node->textInput(text))
    {
      return true;
    }
    node = node->parent();
  }
  return false;
}

std::string FocusManager::selectedText() const
{
  // Bubble up through the focus tree until someone handles the request,
  // mirroring how textInput routes.
  FocusNode* node = m_primaryFocus.get();
  while (node != nullptr)
  {
    Focusable* focusable = node->focusable();
    std::string text;
    if (focusable != nullptr && focusable->selectedText(text))
    {
      return text;
    }
    node = node->parent();
  }
  return std::string();
}

bool FocusManager::primaryFocusAcceptsText() const
{
  FocusNode* node = m_primaryFocus.get();
  while (node != nullptr)
  {
    Focusable* focusable = node->focusable();
    if (focusable != nullptr && focusable->acceptsTextInput())
    {
      return true;
    }
    node = node->parent();
  }
  return false;
}

bool FocusManager::gamepadDispatch(
    const ListenerInvocation& invocation,
    ScriptedDrawable** outDispatchedScriptedDrawable)
{
  dropFocusIfFocusTargetHidden();
  FocusNode* node = m_primaryFocus.get();
  while (node != nullptr)
  {
    if (node->gamepadDispatch(invocation, outDispatchedScriptedDrawable))
    {
      return true;
    }
    node = node->parent();
  }
  return false;
}

void FocusManager::notifyFocusChange(FocusNode* oldFocus, FocusNode* newFocus)
{
  // Find the common ancestor to avoid unnecessary blur/focus notifications
  // on shared ancestors
  FocusNode* commonAncestor = nullptr;
  if (oldFocus != nullptr && newFocus != nullptr)
  {
    // Build a set of ancestors from oldFocus
    std::unordered_set<FocusNode*> oldAncestors;
    for (FocusNode* node = oldFocus; node != nullptr; node = node->parent())
    {
      oldAncestors.insert(node);
    }
    // Find the first ancestor of newFocus that's also an ancestor of
    // oldFocus
    for (FocusNode* node = newFocus; node != nullptr; node = node->parent())
    {
      if (oldAncestors.count(node) > 0)
      {
        commonAncestor = node;
        break;
      }
    }
  }

  // Walk up from oldFocus, clear hasFocus flag and notify blurred
  // Stop at common ancestor (don't blur it or its ancestors)
  FocusNode* current = oldFocus;
  while (current != nullptr && current != commonAncestor && current->hasFocus())
  {
    current->setHasFocus(false);
    current->blurred();
    current = current->parent();
  }

  // Walk up from newFocus, set hasFocus flag and notify focused
  // Stop at common ancestor (don't re-focus it or its ancestors)
  current = newFocus;
  while (current != nullptr && current != commonAncestor &&
         !current->hasFocus())
  {
    current->setHasFocus(true);
    current->focused();
    current = current->parent();
  }

#ifdef WITH_RIVE_TOOLS
  if (m_focusChangedCallback)
  {
    m_focusChangedCallback();
  }

  // Check if we should fire scroll-into-view callback for Dart-mounted
  // artboards. This happens when the focused element is in an artboard
  // whose root has no host (mounted by Dart).
  if (m_scrollIntoViewCallback && newFocus != nullptr)
  {
    AABB bounds;
    if (getRootBounds(newFocus, bounds))
    {
      // Get the immediate artboard containing the focused element
      Artboard* artboard = newFocus->focusable() != nullptr
                               ? newFocus->focusable()->focusableArtboard()
                               : nullptr;
      if (artboard != nullptr)
      {
        // Walk up to find the highest artboard (host == nullptr).
        // This is the artboard that Dart is hosting.
        while (artboard->host() != nullptr &&
               artboard->host()->parentArtboard() != nullptr)
        {
          artboard = artboard->host()->parentArtboard();
        }

        // If this artboard has no host, it's Dart-mounted
        // Pass it to the callback so Dart can find and scroll it
        if (artboard->host() == nullptr)
        {
          m_scrollIntoViewCallback(bounds, artboard);
        }
      }
    }
  }
#endif
}
std::vector<FocusNode*> FocusManager::getTraversableNodes(
    FocusNode* scope) const
{
  auto children = sortedByTabIndex(
      scope != nullptr ? scope->children() : m_rootNodes);
  children.erase(
      std::remove_if(
          children.begin(),
          children.end(),
          [](FocusNode* child) {
            return firstStopInSubtree(child) == nullptr;
          }),
      children.end());
  return children;
}

// The sibling list `node` sits in: its parent's children, or the manager's
// roots when it has no parent.
std::vector<FocusNode*> FocusManager::siblingsOf(FocusNode* node) const
{
  FocusNode* parent = node != nullptr ? node->parent() : nullptr;
  return sortedByTabIndex(parent != nullptr ? parent->children() : m_rootNodes);
}

// Pre-order walk. Forward: into `current`'s own subtree first, then out
// through each ancestor's following siblings. Backward is the exact mirror
// (reverse pre-order): the previous sibling's deepest-last stop, then the
// parent itself, then further out.
//
// edgeBehavior is asked wherever the walk would LEAVE a scope's subtree, which
// is the only place it can mean anything now that a scope can be a stop in its
// own right:
//   parentScope - keep climbing (the root list always behaves this way)
//   closedLoop  - wrap to the other end of that same subtree
//   stop        - stay put; the caller reads "no change" from next == current
//
// Only a scope is asked. A childless node's edgeBehavior has never applied and
// still doesn't (see FocusNode::edgeBehavior) — asking it here would let an
// authored closedLoop on a leaf wrap the leaf onto itself and trap focus.
FocusNode* FocusManager::nextFocusStop(FocusNode* current, bool forward) const
{
  // Nothing focused, or focus is sitting on a node this manager does not
  // own: detachChild takes a subtree out of the manager while deliberately
  // leaving focus on it, and leaves its children hanging off it. Neither the
  // subtree nor the parent chain is ours to walk, so re-enter from the root
  // list instead. Checked before the descent below, not after it, or a
  // detached scope would hand focus to a child the manager no longer knows
  // about.
  if (current == nullptr || current->manager() != this)
  {
    auto roots = sortedByTabIndex(m_rootNodes);
    return forward ? firstStopAmong(roots) : lastStopAmong(roots);
  }

  if (forward)
  {
    // `current`'s own subtree comes next in pre-order, whatever `current`'s
    // flags say: a parent that can't be traversed doesn't take its children
    // out of the order with it.
    for (FocusNode* child : sortedByTabIndex(current->children()))
    {
      FocusNode* stop = firstStopInSubtree(child);
      if (stop != nullptr)
      {
        return stop;
      }
    }
  }

  for (FocusNode* node = current; node != nullptr;)
  {
    // Everything inside `node` has been offered, so this step leaves its
    // subtree and its edge behavior decides whether the walk may.
    if (node->isScope())
    {
      switch (node->edgeBehavior())
      {
        case EdgeBehavior::closedLoop:
          // Wrap within this subtree. With one stop left in it (or
          // none) this lands back on `current` (or nowhere), which
          // the caller reads as no change rather than looping.
          return forward ? firstStopInSubtree(node) : lastStopInSubtree(node);
        case EdgeBehavior::stop:
          return current;
        case EdgeBehavior::parentScope:
          break;
      }
    }

    // `node` belongs to this manager, so it is in the list it claims --
    // the check above sent everything else back to the root list. A miss
    // would leave index at siblings.size(), which reads as "past the end"
    // and lets the walk climb, so there is nothing to guard against here.
    auto siblings = siblingsOf(node);
    auto it = std::find(siblings.begin(), siblings.end(), node);
    size_t index = static_cast<size_t>(it - siblings.begin());
    if (forward)
    {
      for (size_t i = index + 1; i < siblings.size(); i++)
      {
        FocusNode* stop = firstStopInSubtree(siblings[i]);
        if (stop != nullptr)
        {
          return stop;
        }
      }
    }
    else
    {
      for (size_t i = index; i-- > 0;)
      {
        FocusNode* stop = lastStopInSubtree(siblings[i]);
        if (stop != nullptr)
        {
          return stop;
        }
      }
    }

    FocusNode* parent = node->parent();
    if (parent == nullptr)
    {
      // The root list has no owner to ask, so it always reads as
      // parentScope: the walk runs off the end and focus clears.
      return nullptr;
    }
    if (!forward && isFocusStop(parent))
    {
      // Reverse pre-order: a scope precedes its children, so the parent
      // is the predecessor of its first child's subtree. Still INSIDE
      // the parent's subtree, so the parent's edge has no say yet.
      return parent;
    }
    node = parent;
  }
  return nullptr;
}

FocusNode* FocusManager::findNextFocusable(FocusNode* current, bool forward)
    const
{
  FocusNode* next = nextFocusStop(current, forward);
  if (next == current)
  {
    // An edge that says stop, or a closed loop with nothing else left in
    // it. Reported as "didn't move" so a queued traversal request knows it
    // has nothing to retry for.
    return nullptr;
  }
  // A null `next` with focus set is the walk running off the end of the root
  // list, which clears focus. ref_rcp is null-safe and setFocus(nullptr)
  // clears, so this stays one call.
  const_cast<FocusManager*>(this)->setFocus(ref_rcp(next));
  return next;
}

void FocusManager::pressBegan() { m_pressFocus = m_primaryFocus; }

void FocusManager::pressEnded(const Vec2D& rootPosition)
{
  rcp<FocusNode> pressed = std::move(m_pressFocus);
  m_pressFocus = nullptr;
  // Focus moved during the press, or nothing was focused: nothing to blur.
  if (pressed == nullptr || pressed != m_primaryFocus)
  {
    return;
  }
  Focusable* focusable = pressed->focusable();
  if (focusable == nullptr || !focusable->blursOnOutsidePress() ||
      focusable->hitTestFocusable(rootPosition))
  {
    return;
  }
  // Direct, not queued: a focus request the press itself queued still lands
  // afterwards, as it would have blurred this target anyway.
  clearFocus();
}

} // namespace rive
