#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());
        // 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)
{
    auto it =
        std::find(m_focusListeners.begin(), m_focusListeners.end(), listener);
    if (it != m_focusListeners.end())
    {
        m_focusListeners.erase(it);
    }
}

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

void FocusData::removeKeyboardListener(KeyboardListener* listener)
{
    auto it = std::find(m_keyboardListeners.begin(),
                        m_keyboardListeners.end(),
                        listener);
    if (it != m_keyboardListeners.end())
    {
        m_keyboardListeners.erase(it);
    }
}

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

void FocusData::removeTextInputListener(KeyboardListener* listener)
{
    auto it = std::find(m_textInputListeners.begin(),
                        m_textInputListeners.end(),
                        listener);
    if (it != m_textInputListeners.end())
    {
        m_textInputListeners.erase(it);
    }
}

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

void FocusData::removeGamepadListener(GamepadListener* listener)
{
    auto it = std::find(m_gamepadListeners.begin(),
                        m_gamepadListeners.end(),
                        listener);
    if (it != m_gamepadListeners.end())
    {
        m_gamepadListeners.erase(it);
    }
}

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;
    for (auto* listener : m_keyboardListeners)
    {
        if (listener->keyInput(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 KeyboardListenerGroup's
    // key/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::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();
    }
}