/*
 * 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/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 (focusNodeTraversable) so any live children stay reachable.
        return !node->hadFocusable();
    }
    return f->isEligibleForFocusTraversal();
}

static bool focusNodeEligibleForTraversal(FocusNode* node)
{
    if (node == nullptr || !node->canTraverse())
    {
        return false;
    }
    return focusNodeEligibleForFocus(node);
}

// Defined later in this file; used by setFocus to descend a scope to its first
// eligible leaf.
static FocusNode* getFirstLeaf(FocusNode* node, const FocusManager* manager);

// 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()
{
    if (m_primaryFocus == nullptr ||
        focusNodeEligibleForTraversal(m_primaryFocus.get()))
    {
        return;
    }

    // Walk ancestors outward and take the first that can still offer a focus
    // stop. getFirstLeaf does the choosing at each level, so it prefers
    // another eligible leaf under that ancestor (a sibling of what just
    // disappeared) and settles for the ancestor itself only when it is an
    // eligible leaf in its own right. That keeps the focus-rests-on-a-leaf
    // invariant intact.
    for (FocusNode* ancestor = m_primaryFocus->parent(); ancestor != nullptr;
         ancestor = ancestor->parent())
    {
        FocusNode* leaf = getFirstLeaf(ancestor, this);
        if (leaf != nullptr)
        {
            setFocus(ref_rcp(leaf));
            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();
}

void FocusManager::descendFocusToLeaf(const Artboard* rootArtboard)
{
    applyDescendFocusToLeaf(rootArtboard, /*allRoots=*/false);
}

void FocusManager::descendFocusToLeafAllRoots()
{
    applyDescendFocusToLeaf(nullptr, /*allRoots=*/true);
}

void FocusManager::applyDescendFocusToLeaf(const Artboard* rootArtboard,
                                           bool allRoots)
{
    // Fast path for the overwhelmingly common state: focus already rests on a
    // leaf.
    if (m_primaryFocus == nullptr || m_primaryFocus->children().empty())
    {
        return;
    }
    // getFirstLeaf returns the node itself when it is still a leaf, so a
    // different result means the target has gained eligible traversable
    // descendants since focus landed on it and is now a scope.
    FocusNode* leaf = getFirstLeaf(m_primaryFocus.get(), this);
    if (leaf == nullptr || leaf == m_primaryFocus.get())
    {
        return;
    }
    if (!allRoots && belongsToAnotherRoot(leaf, rootArtboard))
    {
        return;
    }
    setFocus(ref_rcp(leaf));
}

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 always rests on a leaf: if handed a scope (a node with eligible
    // traversable descendants), descend to its first eligible leaf — matching
    // Tab/arrow traversal, which never lands focus on a scope. Falls back to
    // the node itself when it has no eligible leaf.
    //
    // Gate the descent on the requested target being eligible for focus, so a
    // programmatic focus on an ineligible target (canFocus==false, collapsed,
    // hidden, opacity 0, ...) stays a no-op as before, rather than reaching an
    // eligible descendant and bypassing the early-return guards below.
    if (node != nullptr && focusNodeEligibleForFocus(node.get()))
    {
        FocusNode* leaf = getFirstLeaf(node.get(), this);
        if (leaf != nullptr)
        {
            node = ref_rcp(leaf);
        }
    }

    if (node == m_primaryFocus)
    {
        return;
    }

    if (node && !node->canFocus())
    {
        return;
    }

    if (node != nullptr && !focusNodeEligibleForFocus(node.get()))
    {
        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();
    }
}

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

bool FocusManager::focusPrevious()
{
    dropFocusIfFocusTargetHidden();
    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;
}

static bool focusNodeTraversable(FocusNode* node);

// Helper to check if a node is a leaf (no traversable children). Uses the same
// predicate as Tab traversal so directional navigation and Tab agree on what
// counts as a scope: a child that is a transparent structural scope (canFocus
// false) still makes this node a non-leaf when a focusable lives beneath it.
static bool isLeaf(FocusNode* node)
{
    for (const auto& child : node->children())
    {
        if (focusNodeTraversable(child.get()))
        {
            return false;
        }
    }
    return true;
}

// Helper to collect all traversable leaf focus nodes recursively
// Only collects leaves (nodes with no traversable children) to match
// next/prev behavior
static void collectAllTraversableNodes(const std::vector<rcp<FocusNode>>& nodes,
                                       std::vector<FocusNode*>& result)
{
    for (const auto& node : nodes)
    {
        if (node->canFocus() && node->canTraverse() && isLeaf(node.get()) &&
            focusNodeEligibleForTraversal(node.get()))
        {
            result.push_back(node.get());
        }
        // Recurse into children
        collectAllTraversableNodes(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;
    collectAllTraversableNodes(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();
    FocusNode* next =
        findNodeInDirection(m_primaryFocus.get(), Direction::left);
    if (next)
    {
        setFocus(ref_rcp(next));
        return true;
    }
    return false;
}

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

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

bool FocusManager::focusDown()
{
    dropFocusIfFocusTargetHidden();
    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();
    // 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::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::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
}

static bool hasEligibleTraversableChildInFocusTree(FocusNode* node);

// True if this node is a focusable traversal target itself, or the transparent
// scope of a data-bound nested artboard that we descend through to reach its
// focusable descendants.
static bool focusNodeTraversable(FocusNode* node)
{
    if (node == nullptr)
    {
        return false;
    }
    if (focusNodeEligibleForTraversal(node))
    {
        return true;
    }
    // The data-bound nested-artboard scope is the only runtime FocusNode with
    // no Focusable: descend through such an unbacked node. Authored
    // canFocus=false nodes keep their Focusable and stay non-traversable
    if (node->focusable() != nullptr)
    {
        return false;
    }
    return hasEligibleTraversableChildInFocusTree(node);
}

std::vector<FocusNode*> FocusManager::getTraversableNodes(
    FocusNode* scope) const
{
    std::vector<FocusNode*> result;

    // Get children from scope or root nodes
    const std::vector<rcp<FocusNode>>* childList =
        scope ? &scope->children() : &m_rootNodes;

    for (const auto& child : *childList)
    {
        if (focusNodeTraversable(child.get()))
        {
            result.push_back(child.get());
        }
    }

    // Sort by tabIndex, then by tree order (which is insertion order)
    std::stable_sort(result.begin(),
                     result.end(),
                     [](FocusNode* a, FocusNode* b) {
                         return a->tabIndex() < b->tabIndex();
                     });

    return result;
}

static bool hasEligibleTraversableChildInFocusTree(FocusNode* node)
{
    for (const auto& ch : node->children())
    {
        if (focusNodeTraversable(ch.get()))
        {
            return true;
        }
    }
    return false;
}

// First eligible leaf under node (deepest first); nullptr if none
static FocusNode* getFirstLeaf(FocusNode* node, const FocusManager* manager)
{
    if (node == nullptr)
    {
        return nullptr;
    }
    auto children = manager->getTraversableNodes(node);
    for (FocusNode* ch : children)
    {
        FocusNode* leaf = getFirstLeaf(ch, manager);
        if (leaf != nullptr)
        {
            return leaf;
        }
    }
    // `children` is already the focusNodeTraversable-filtered child list, which
    // is the exact predicate hasEligibleTraversableChildInFocusTree applies, so
    // empty == "no traversable children". Testing it here instead re-uses that
    // scan rather than repeating it, and short-circuits the ancestor walk in
    // focusNodeEligibleForTraversal for every non-leaf.
    if (children.empty() && focusNodeEligibleForTraversal(node))
    {
        return node;
    }
    return nullptr;
}

static FocusNode* getLastLeaf(FocusNode* node, const FocusManager* manager)
{
    if (node == nullptr)
    {
        return nullptr;
    }
    auto children = manager->getTraversableNodes(node);
    for (auto it = children.rbegin(); it != children.rend(); ++it)
    {
        FocusNode* leaf = getLastLeaf(*it, manager);
        if (leaf != nullptr)
        {
            return leaf;
        }
    }
    // Same reuse as getFirstLeaf.
    if (children.empty() && focusNodeEligibleForTraversal(node))
    {
        return node;
    }
    return nullptr;
}

static FocusNode* firstEligibleLeafFrom(
    const std::vector<FocusNode*>& traversable,
    bool forward,
    const FocusManager* manager)
{
    if (forward)
    {
        for (FocusNode* t : traversable)
        {
            FocusNode* leaf = getFirstLeaf(t, manager);
            if (leaf != nullptr)
            {
                return leaf;
            }
        }
    }
    else
    {
        for (auto it = traversable.rbegin(); it != traversable.rend(); ++it)
        {
            FocusNode* leaf = getLastLeaf(*it, manager);
            if (leaf != nullptr)
            {
                return leaf;
            }
        }
    }
    return nullptr;
}

FocusNode* FocusManager::findNextFocusable(FocusNode* current,
                                           bool forward) const
{
    FocusNode* scope = current ? current->parent() : nullptr;
    auto traversable = getTraversableNodes(scope);

    if (traversable.empty())
    {
        if (scope)
        {
            return findNextFocusable(scope, forward);
        }
        return nullptr;
    }

    auto it = std::find(traversable.begin(), traversable.end(), current);
    FocusNode* next = nullptr;

    if (it == traversable.end())
    {
        next = firstEligibleLeafFrom(traversable, forward, this);
    }
    else
    {
        size_t idx = static_cast<size_t>(it - traversable.begin());
        if (forward)
        {
            for (size_t i = idx + 1; i < traversable.size(); i++)
            {
                next = getFirstLeaf(traversable[i], this);
                if (next != nullptr)
                {
                    break;
                }
            }
            if (next == nullptr)
            {
                EdgeBehavior edge =
                    scope ? scope->edgeBehavior() : EdgeBehavior::parentScope;
                switch (edge)
                {
                    case EdgeBehavior::closedLoop:
                        for (size_t i = 0; i < idx; i++)
                        {
                            next = getFirstLeaf(traversable[i], this);
                            if (next != nullptr)
                            {
                                break;
                            }
                        }
                        if (next == nullptr)
                        {
                            next =
                                firstEligibleLeafFrom(traversable, true, this);
                        }
                        break;
                    case EdgeBehavior::stop:
                        next = current;
                        break;
                    case EdgeBehavior::parentScope:
                        if (scope)
                        {
                            return findNextFocusable(scope, forward);
                        }
                        next = nullptr;
                        break;
                }
            }
        }
        else
        {
            for (int i = static_cast<int>(idx) - 1; i >= 0; i--)
            {
                next = getLastLeaf(traversable[static_cast<size_t>(i)], this);
                if (next != nullptr)
                {
                    break;
                }
            }
            if (next == nullptr)
            {
                EdgeBehavior edge =
                    scope ? scope->edgeBehavior() : EdgeBehavior::parentScope;
                switch (edge)
                {
                    case EdgeBehavior::closedLoop:
                        for (int i = static_cast<int>(traversable.size()) - 1;
                             i > static_cast<int>(idx);
                             i--)
                        {
                            next =
                                getLastLeaf(traversable[static_cast<size_t>(i)],
                                            this);
                            if (next != nullptr)
                            {
                                break;
                            }
                        }
                        if (next == nullptr)
                        {
                            next =
                                firstEligibleLeafFrom(traversable, false, this);
                        }
                        break;
                    case EdgeBehavior::stop:
                        next = current;
                        break;
                    case EdgeBehavior::parentScope:
                        if (scope)
                        {
                            return findNextFocusable(scope, forward);
                        }
                        next = nullptr;
                        break;
                }
            }
        }
    }

    if (next != current)
    {
        const_cast<FocusManager*>(this)->setFocus(ref_rcp(next));
        return next;
    }
    return nullptr;
}

} // namespace rive
