#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/focus_input_traversal.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/text/text_input.hpp"
#include "rive/transform_component.hpp"
#include "rive/world_transform_component.hpp"
#include <algorithm>

using namespace rive;

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

        // Remove from manager if registered
        auto* manager = m_focusNode->manager();
        if (manager != nullptr)
        {
            manager->removeChild(m_focusNode);
        }
        // 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(m_CanFocus);
        m_focusNode->canTouch(m_CanTouch);
        m_focusNode->canTraverse(m_CanTraverse);
        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::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)
{
    // Notify listeners
    bool handled = false;
    for (auto* listener : m_keyboardListeners)
    {
        handled = listener->keyInput(value, modifiers, isPressed, isRepeat);
        if (handled)
        {
            break;
        }
    }
    // Search only the children of this FocusData's owner (parent Node),
    // not the entire artboard.
    auto* parentNode = parent();
    if (parentNode == nullptr || !parentNode->is<Node>())
    {
        return handled;
    }
    // If the parent is Focusable and immediately handles the input, we're done!
    auto* focusable = Focusable::from(parentNode);
    if (focusable != nullptr &&
        focusable->keyInput(value, modifiers, isPressed, isRepeat))
    {
        return true;
    }
    // If it was already handled, we're done too!
    if (handled)
    {
        return handled;
    }
    for (auto* child : parentNode->as<Node>()->children())
    {
        if (sendInputToFocusableChildren(child,
                                         &Focusable::keyInput,
                                         value,
                                         modifiers,
                                         isPressed,
                                         isRepeat))
        {
            return true;
        }
    }
    return false;
}

bool FocusData::textInput(const std::string& text)
{
    // Search only the children of this FocusData's owner (parent Node),
    // not the entire artboard.
    auto* parentNode = parent();
    if (parentNode == nullptr || !parentNode->is<Node>())
    {
        return false;
    }

    // If the parent is Focusable and immediately handles the input, we're done!
    auto* focusable = Focusable::from(parentNode);
    if (focusable != nullptr && focusable->textInput(text))
    {
        return true;
    }

    // Look through children for a Focusable to handle the text input.
    for (auto* child : parentNode->as<Node>()->children())
    {
        if (sendInputToFocusableChildren(child, &Focusable::textInput, text))
        {
            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())
    {
        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())
    {
        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.
        float targetX = effectiveScrollX + deltaX;
        float targetY = effectiveScrollY + deltaY;
        constraint->scrollToPosition(targetX, targetY);
    }
}

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

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

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

void FocusData::canFocusChanged()
{
    if (m_focusNode != nullptr)
    {
        m_focusNode->canFocus(m_CanFocus);
    }
}

void FocusData::canTouchChanged()
{
    if (m_focusNode != nullptr)
    {
        m_focusNode->canTouch(m_CanTouch);
    }
}

void FocusData::canTraverseChanged()
{
    if (m_focusNode != nullptr)
    {
        m_focusNode->canTraverse(m_CanTraverse);
    }
}

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();
    }
}

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

    auto* parentComponent = parent();
    if (parentComponent != nullptr && parentComponent->is<LayoutComponent>())
    {
        // LayoutComponent has worldBounds based on its layout dimensions
        AABB bounds = parentComponent->as<LayoutComponent>()->worldBounds();
        // Transform to root artboard space (handles nested artboards)
        auto* ab = artboard();
        if (ab != nullptr)
        {
            Vec2D min = ab->rootTransform(Vec2D(bounds.minX, bounds.minY));
            Vec2D max = ab->rootTransform(Vec2D(bounds.maxX, bounds.maxY));
            bounds = AABB(min.x, min.y, max.x, max.y);
        }
        m_focusNode->worldBounds(bounds);
    }
    else
    {
        // For non-layout parents, clear bounds (will fall back to position)
        m_focusNode->clearWorldBounds();
    }
}