#include "rive/nested_artboard.hpp"
#include "rive/artboard.hpp"
#include "rive/backboard.hpp"
#include "rive/file.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/input/focusable.hpp"
#include "rive/nested_animation.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include "rive/data_bind/data_bind_path.hpp"
#include "rive/clip_result.hpp"
#include "rive/text/text_input.hpp"
#include <limits>
#include <cassert>

using namespace rive;

NestedArtboard::NestedArtboard() {}
NestedArtboard::~NestedArtboard()
{
    // Release dependencies of nested animations BEFORE m_Instance is destroyed.
    // The nested animations (like NestedStateMachine) hold
    // StateMachineInstances that reference m_Instance. If we don't release them
    // here, their destructors (called later when the parent artboard destroys
    // them from m_Objects) will try to access the already-freed m_Instance.
    for (auto& animation : m_NestedAnimations)
    {
        animation->releaseDependencies();
    }
    // Also release the bound state machine's dependencies if it exists
    if (m_boundNestedStateMachine)
    {
        m_boundNestedStateMachine->releaseDependencies();
    }

    // Clear ViewModelInstance references to break potential ref cycles.
    // The ViewModelInstance and its property values are also in the artboard's
    // m_Objects list and will be cleaned up there.
    m_viewModelInstance = nullptr;
    m_statefulViewModelInstance = nullptr;
}

Core* NestedArtboard::clone() const
{
    NestedArtboard* nestedArtboard =
        static_cast<NestedArtboard*>(NestedArtboardBase::clone());
    nestedArtboard->file(file());
    if (m_referencedArtboard == nullptr)
    {
        return nestedArtboard;
    }
    auto ni = m_referencedArtboard->instance();
    nestedArtboard->referencedArtboard(ni.release());
    return nestedArtboard;
}

void NestedArtboard::nest(Artboard* artboard)
{
    m_referencedArtboard = artboard;
    if (!m_referencedArtboard->isInstance())
    {
        // We're just marking the source artboard so we can later instance from
        // it. No need to advance it or change any of its properties.
        // E.g. at import time, we return here.
        return;
    }
    m_referencedArtboard->frameOrigin(false);
    m_referencedArtboard->opacity(renderOpacity());
    m_referencedArtboard->volume(artboard->volume());
    m_Instance = nullptr;
    if (artboard->isInstance())
    {
        m_Instance.reset(
            static_cast<ArtboardInstance*>(artboard)); // take ownership
    }
    // This allows for swapping after initial load (after onAddedClean has
    // already been called).
    m_referencedArtboard->host(this);
}

bool NestedArtboard::tryScheduleBindStateful()
{

    if (m_statefulViewModelInstance != nullptr && artboardInstance())
    {
        m_hasPendingStatefulBinding = true;
        return true;
    }
    return false;
}

void NestedArtboard::bindStateful()
{
    m_hasPendingStatefulBinding = false;
    bindArtboardInstance(m_statefulViewModelInstance, m_dataContext);
}

void NestedArtboard::bindArtboardInstance(rcp<ViewModelInstance> instance,
                                          rcp<DataContext> parent)
{
    artboardInstance()->bindViewModelInstance(instance, parent);
    for (auto& animation : m_NestedAnimations)
    {
        if (animation->is<NestedStateMachine>())
        {
            animation->as<NestedStateMachine>()->dataContext(
                artboardInstance()->dataContext());
        }
    }
}

void NestedArtboard::clearNestedAnimations()
{
    for (auto& animation : m_NestedAnimations)
    {
        // Release the nested animation dependencies. The file will take care of
        // destroying the nested animation itself.
        animation->releaseDependencies();
    }
    m_NestedAnimations.clear();
}

void NestedArtboard::updateArtboard(
    ViewModelInstanceArtboard* viewModelInstanceArtboard)
{
    clearDataContext();
    clearNestedAnimations();
    m_boundNestedStateMachine = nullptr;
    // If asset == nullptr and propertyValue == -1, it means that the user
    // explicitly set the asset to null, so only in that case we clear the
    // artboard
    if (viewModelInstanceArtboard != nullptr &&
        viewModelInstanceArtboard->asset() == nullptr &&
        viewModelInstanceArtboard->propertyValue() == -1)
    {
        if (m_referencedArtboard)
        {
            m_referencedArtboard->host(nullptr);
            m_referencedArtboard = nullptr;
        }
        m_Instance = nullptr;
        return;
    }

    Artboard* artboard =
        findArtboard(viewModelInstanceArtboard, parentArtboard(), m_file);
    if (artboard != nullptr)
    {
        auto artboardInstance = artboard->instance();
        if (artboard->stateMachineCount() > 0)
        {

            auto nestedStateMachine = new NestedStateMachine();
            nestedStateMachine->animationId(0);
            nestedStateMachine->initializeAnimation(artboardInstance.get());
            addNestedAnimation(nestedStateMachine);

            m_boundNestedStateMachine.reset(static_cast<NestedStateMachine*>(
                nestedStateMachine)); // take ownership
        }
        referencedArtboard(artboardInstance.release());
        if (viewModelInstanceArtboard->boundViewModelInstance())
        {
            bindViewModelInstance(
                viewModelInstanceArtboard->boundViewModelInstance(),
                m_dataContext);
        }
        else if (tryScheduleBindStateful())
        {
            bindStateful();
        }
        else if (m_dataContext != nullptr && m_viewModelInstance == nullptr)
        {
            internalDataContext(m_dataContext);
        }
        else if (m_viewModelInstance != nullptr)
        {
            bindViewModelInstance(m_viewModelInstance, m_dataContext);
        }
        // TODO: @hernan review what dirt to add
        addDirt(ComponentDirt::Filthy);
    }
}

static Mat2D makeTranslate(const Artboard* artboard)
{
    return Mat2D::fromTranslate(-artboard->originX() * artboard->width(),
                                -artboard->originY() * artboard->height());
}

void NestedArtboard::draw(Renderer* renderer)
{
    if (m_needsSaveOperation)
    {
        renderer->save();
    }
    renderer->transform(worldTransform());
    m_referencedArtboard->drawInternal(renderer);
    if (m_needsSaveOperation)
    {
        renderer->restore();
    }
}

bool NestedArtboard::willDraw()
{
    return Super::willDraw() && m_referencedArtboard != nullptr;
}

Core* NestedArtboard::hitTest(HitInfo* hinfo, const Mat2D& xform)
{
    if (m_referencedArtboard == nullptr)
    {
        return nullptr;
    }
    hinfo->mounts.push_back(this);
    auto mx = xform * worldTransform() * makeTranslate(m_referencedArtboard);
    if (auto c = m_referencedArtboard->hitTest(hinfo, mx))
    {
        return c;
    }
    hinfo->mounts.pop_back();
    return nullptr;
}

bool NestedArtboard::hitTestHost(const Vec2D& position,
                                 bool skipOnUnclipped,
                                 ArtboardInstance* artboard)
{
    return parent()->hitTestPoint(worldTransform() * position,
                                  skipOnUnclipped,
                                  false);
}

Vec2D NestedArtboard::hostTransformPoint(const Vec2D& vec,
                                         ArtboardInstance* artboardInstance)
{
    auto localVec = Vec2D::transformMat2D(vec, worldTransform());
    auto ab = artboard();
    return ab ? ab->rootTransform(localVec) : localVec;
}

Mat2D NestedArtboard::worldTransformForArtboard(ArtboardInstance*)
{
    return worldTransform();
}

StatusCode NestedArtboard::import(ImportStack& importStack)
{
    importDataBindPath(importStack);
    auto backboardImporter =
        importStack.latest<BackboardImporter>(Backboard::typeKey);
    if (backboardImporter == nullptr)
    {
        return StatusCode::MissingObject;
    }
    backboardImporter->addArtboardReferencer(this);

    return Super::import(importStack);
}

void NestedArtboard::addNestedAnimation(NestedAnimation* nestedAnimation)
{
    m_NestedAnimations.push_back(nestedAnimation);
}

StatusCode NestedArtboard::onAddedClean(CoreContext* context)
{
    // N.B. The nested instance will be null here for the source artboards.
    // Instances will have a nestedInstance available. This is a good thing as
    // it ensures that we only instance animations in artboard instances. It
    // does require that we always use an artboard instance (not just the source
    // artboard) when working with nested artboards, but in general this is good
    // practice for any loaded Rive file.
    assert(m_referencedArtboard == nullptr ||
           m_referencedArtboard == m_Instance.get());

    if (m_Instance)
    {
        for (auto animation : m_NestedAnimations)
        {
            animation->initializeAnimation(m_Instance.get());
        }
        m_referencedArtboard->host(this);
    }

    // ViewModelInstance children are only added to NestedArtboards
    // that wrap a stateful component Artboard.
    for (auto child : children())
    {
        if (child->is<ViewModelInstance>())
        {
            auto vmi = child->as<ViewModelInstance>();
            // Take ownership of the VMI's initial ref count. The VMI starts
            // with ref count 1 from construction. The rcp constructor takes
            // this ref without adding another. NestedArtboard now owns the VMI.
            m_statefulViewModelInstance = rcp<ViewModelInstance>(vmi);
            m_file->completeViewModelProperties(
                m_statefulViewModelInstance.get());
            break;
        }
    }
    tryScheduleBindStateful();

    return Super::onAddedClean(context);
}

void NestedArtboard::update(ComponentDirt value)
{
    Super::update(value);
    if (m_referencedArtboard == nullptr)
    {
        return;
    }
    if (hasDirt(value, ComponentDirt::WorldTransform))
    {
        // Mark semantic bounds dirty for nodes inside the nested artboard.
        // Their root-space bounds depend on the host's world transform.
        if (m_Instance != nullptr)
        {
            m_Instance->markSemanticBoundaryTransformDirty();
        }
    }
    if (hasDirt(value, ComponentDirt::RenderOpacity))
    {
        m_referencedArtboard->opacity(renderOpacity());
    }
    if (hasDirt(value, ComponentDirt::Components))
    {
        // We intentionally discard whether or not this updated because by the
        // end of the pass all the dirt is removed and only another advance of
        // animations/statemachines can re-add it.
        m_referencedArtboard->updatePass(false);
    }
}

bool NestedArtboard::collapse(bool value)
{
    if (!Super::collapse(value))
    {
        return false;
    }

    auto* nestedInstance = artboardInstance();
    if (nestedInstance == nullptr)
    {
        return true;
    }
    // Semantic-only collapse via the artboard boundary node. Only touches
    // SemanticData nodes — non-semantic components stay untouched.
    nestedInstance->collapseSemanticBoundary(value);
    return true;
}

bool NestedArtboard::hasNestedStateMachines() const
{
    for (auto animation : m_NestedAnimations)
    {
        if (animation->is<NestedStateMachine>())
        {
            return true;
        }
    }
    return false;
}

Span<NestedAnimation*> NestedArtboard::nestedAnimations()
{
    return m_NestedAnimations;
}

NestedArtboard* NestedArtboard::nestedArtboard(std::string name) const
{
    if (m_Instance != nullptr)
    {
        return m_Instance->nestedArtboard(name);
    }
    return nullptr;
}

NestedStateMachine* NestedArtboard::stateMachine(std::string name) const
{
    for (auto animation : m_NestedAnimations)
    {
        if (animation->is<NestedStateMachine>() && animation->name() == name)
        {
            return animation->as<NestedStateMachine>();
        }
    }
    return nullptr;
}

NestedInput* NestedArtboard::input(std::string name) const
{
    return input(name, "");
}

NestedInput* NestedArtboard::input(std::string name,
                                   std::string stateMachineName) const
{
    if (!stateMachineName.empty())
    {
        auto nestedSM = stateMachine(stateMachineName);
        if (nestedSM != nullptr)
        {
            return nestedSM->input(name);
        }
    }
    else
    {
        for (auto animation : m_NestedAnimations)
        {
            if (animation->is<NestedStateMachine>())
            {
                auto input = animation->as<NestedStateMachine>()->input(name);
                if (input != nullptr)
                {
                    return input;
                }
            }
        }
    }
    return nullptr;
}

bool NestedArtboard::worldToLocal(Vec2D world, Vec2D* local)
{
    assert(local != nullptr);
    if (m_referencedArtboard == nullptr)
    {
        return false;
    }
    Mat2D toMountedArtboard;
    if (!worldTransform().invert(&toMountedArtboard))
    {
        return false;
    }

    *local = toMountedArtboard * world;

    return true;
}

Vec2D NestedArtboard::measureLayout(float width,
                                    LayoutMeasureMode widthMode,
                                    float height,
                                    LayoutMeasureMode heightMode)
{
    return Vec2D(std::min(widthMode == LayoutMeasureMode::undefined
                              ? std::numeric_limits<float>::max()
                              : width,
                          m_Instance ? m_Instance->width() : 0.0f),
                 std::min(heightMode == LayoutMeasureMode::undefined
                              ? std::numeric_limits<float>::max()
                              : height,
                          m_Instance ? m_Instance->height() : 0.0f));
}

void NestedArtboard::controlSize(Vec2D size,
                                 LayoutScaleType widthScaleType,
                                 LayoutScaleType heightScaleType,
                                 LayoutDirection direction)
{}

void NestedArtboard::decodeDataBindPathIds(Span<const uint8_t> value)
{
    decodeDataBindPath(value);
}

void NestedArtboard::copyDataBindPathIds(const NestedArtboardBase& object)
{
    copyDataBindPath(object.as<NestedArtboard>()->dataBindPath());
}

void NestedArtboard::internalDataContext(rcp<DataContext> value)
{
    m_dataContext = value;
    m_viewModelInstance = nullptr;

    if (artboardInstance() != nullptr)
    {
        // If we have a stateful ViewModelInstance, bind it to the artboard
        // instance.
        if (tryScheduleBindStateful())
        {
            return;
        }

        // Non-stateful path: just propagate the data context.
        artboardInstance()->internalDataContext(value);
        for (auto& animation : m_NestedAnimations)
        {
            if (animation->is<NestedStateMachine>())
            {
                animation->as<NestedStateMachine>()->dataContext(value);
            }
        }
    }
}

void NestedArtboard::relinkDataContext(rcp<ViewModelInstance> viewModelInstance)
{
    m_viewModelInstance = viewModelInstance;
    auto instance = artboardInstance(0);
    if (instance && !instance->isStateful())
    {
        auto dataContext = instance->dataContext();
        if (dataContext != nullptr)
        {
            if (dataContext->viewModelInstance() != viewModelInstance)
            {
                dataContext->viewModelInstance(viewModelInstance);
            }
        }
        instance->relinkDataContext();
    }
}

void NestedArtboard::clearDataContext()
{
    if (artboardInstance() != nullptr)
    {
        artboardInstance()->clearDataContext();
        for (auto& animation : m_NestedAnimations)
        {
            if (animation->is<NestedStateMachine>())
            {
                animation->as<NestedStateMachine>()->clearDataContext();
            }
        }
    }
}

void NestedArtboard::unbind()
{
    if (artboardInstance() != nullptr)
    {
        artboardInstance()->unbind();
    }
}

void NestedArtboard::updateDataBinds()
{
    if (artboardInstance() != nullptr && !isPaused())
    {
        artboardInstance()->updateDataBinds();
    }
}

void NestedArtboard::bindViewModelInstance(
    rcp<ViewModelInstance> viewModelInstance,
    rcp<DataContext> parent)
{
    m_dataContext = parent;
    m_viewModelInstance = viewModelInstance;
    if (artboardInstance() != nullptr)
    {
        // Stateful nested artboards must keep their own instance as the local
        // root context, while the incoming instance remains the parent context.
        auto instanceToBind = m_statefulViewModelInstance != nullptr
                                  ? m_statefulViewModelInstance
                                  : viewModelInstance;
        bindArtboardInstance(instanceToBind, parent);
    }
}

float NestedArtboard::calculateLocalElapsedSeconds(float elapsedSeconds)
{
    auto localElapsedSeconds = elapsedSeconds * (speed() >= 0 ? speed() : 1);
    if (quantize() >= 0)
    {
        m_cumulatedSeconds += localElapsedSeconds;
        auto quantizedSeconds = 1 / quantize();
        if (m_cumulatedSeconds > quantizedSeconds)
        {
            localElapsedSeconds =
                std::floor(m_cumulatedSeconds / quantizedSeconds) *
                quantizedSeconds;
            m_cumulatedSeconds -= localElapsedSeconds;
        }
        else
        {
            localElapsedSeconds = 0;
        }
    }
    return localElapsedSeconds;
}

bool NestedArtboard::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
    if (m_referencedArtboard == nullptr || isCollapsed() || isPaused())
    {
        return false;
    }
    if (m_hasPendingStatefulBinding)
    {
        bindStateful();
    }
    bool keepGoing = false;
    bool advanceNested =
        (flags & AdvanceFlags::AdvanceNested) == AdvanceFlags::AdvanceNested;
    auto localElapsedSeconds = calculateLocalElapsedSeconds(elapsedSeconds);
    bool newFrame = (flags & AdvanceFlags::NewFrame) == AdvanceFlags::NewFrame;
    // If the elapsed time is 0 because of quantization, we still want to
    // continue advancing until the cumulated time is flushed
    if (localElapsedSeconds == 0 && quantize() >= 0 && newFrame)
    {
        return true;
    }
    if (advanceNested)
    {
        for (auto animation : m_NestedAnimations)
        {
            // If it is not a new frame, we only advance state machines. And we
            // first validate whether their state has changed. Then and only
            // then we advance the state machine. This avoids triggering dirt
            // from advances that make intermediate value changes but finally
            // settle in the same value
            if (!newFrame)
            {
                if (animation->is<NestedStateMachine>())
                {
                    if (animation->as<NestedStateMachine>()->tryChangeState())
                    {
                        if (animation->advance(localElapsedSeconds, newFrame))
                        {
                            keepGoing = true;
                        }
                    }
                }
            }
            else
            {

                if (animation->advance(localElapsedSeconds, newFrame))
                {
                    keepGoing = true;
                }
            }
        }
    }

    auto advancingFlags = flags & ~AdvanceFlags::IsRoot;
    if (m_referencedArtboard->advanceInternal(localElapsedSeconds,
                                              advancingFlags))
    {
        keepGoing = true;
    }
    if (m_referencedArtboard->hasDirt(ComponentDirt::Components))
    {
        // The animation(s) caused the artboard to need an update.
        addDirt(ComponentDirt::Components);
    }

    return keepGoing;
}

void NestedArtboard::reset()
{
    if (m_referencedArtboard)
    {
        m_referencedArtboard->reset();
    }
    if (m_statefulViewModelInstance != nullptr)
    {
        m_statefulViewModelInstance->advanced();
    }
}

void NestedArtboard::file(File* value) { m_file = value; }

File* NestedArtboard::file() const { return m_file; }

int NestedArtboard::referencedArtboardId() { return artboardId(); }

void NestedArtboard::referencedArtboard(Artboard* artboard)
{
    assert(artboard != nullptr);
    ArtboardReferencer::referencedArtboard(artboard);
    nest(artboard);
    tryScheduleBindStateful();
}