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

    m_viewModelInstance = nullptr;
    // Release the owned bound VMI. The borrowed stateful child VMI is cleaned
    // up by the parent Artboard's m_Objects teardown.
    if (m_ownsActiveVmi && m_activeViewModelInstance != nullptr)
    {
        m_activeViewModelInstance->unref();
    }
    m_activeViewModelInstance = nullptr;
    m_ownsActiveVmi = false;
    m_hasPendingStatefulBinding = false;
}

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_activeViewModelInstance != nullptr && artboardInstance())
    {
        m_hasPendingStatefulBinding = true;
        return true;
    }
    return false;
}

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

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

ViewModelInstance* NestedArtboard::findStatefulChildVmi() const
{
    for (auto child : children())
    {
        if (child->is<ViewModelInstance>())
        {
            return child->as<ViewModelInstance>();
        }
    }
    return nullptr;
}

void NestedArtboard::setActiveViewModelInstance(ViewModelInstance* vmi,
                                                bool owns)
{
    if (m_activeViewModelInstance == vmi)
    {
        // Same pointer; tolerate an ownership refresh only when both states
        // agree it's still owned (idempotent reuse of the bound instance).
        return;
    }
    if (m_ownsActiveVmi && m_activeViewModelInstance != nullptr)
    {
        m_activeViewModelInstance->unref();
    }
    m_activeViewModelInstance = vmi;
    m_ownsActiveVmi = owns;
}

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;
        setActiveViewModelInstance(nullptr, false);
        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 (isStateful())
        {
            auto statefulChild = findStatefulChildVmi();
            if (statefulChild != nullptr &&
                statefulChild->viewModelId() == artboard->viewModelId())
            {
                // Source artboard uses the same VM as the stateful child:
                // borrow the child instance.
                setActiveViewModelInstance(statefulChild, false);
            }
            else if (m_ownsActiveVmi && m_activeViewModelInstance != nullptr &&
                     m_activeViewModelInstance->viewModelId() ==
                         artboard->viewModelId())
            {
                // Already holding a bound instance for this VM; reuse.
            }
            else
            {
                auto vm = m_file != nullptr
                              ? m_file->viewModel(artboard->viewModelId())
                              : nullptr;
                rcp<ViewModelInstance> newBound =
                    vm != nullptr ? m_file->createDefaultViewModelInstance(vm)
                                  : nullptr;
                ViewModelInstance* raw = newBound.release();
                setActiveViewModelInstance(raw, /*owns=*/raw != nullptr);
                if (raw != nullptr)
                {
                    m_file->completeViewModelProperties(raw);
                }
            }
        }
        else
        {
            setActiveViewModelInstance(nullptr, false);
        }

        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. We borrow the child VMI as the
    // initial active binding; the parent Artboard's m_Objects teardown owns
    // its lifetime.
    if (auto vmi = findStatefulChildVmi())
    {
        m_activeViewModelInstance = vmi;
        m_ownsActiveVmi = false;
        m_file->completeViewModelProperties(vmi);
    }
    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 && !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.
        ViewModelInstance* instanceToBind = m_activeViewModelInstance != nullptr
                                                ? m_activeViewModelInstance
                                                : viewModelInstance.get();
        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_activeViewModelInstance != nullptr)
    {
        m_activeViewModelInstance->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();
}