#include "rive/nested_artboard.hpp"
#include "rive/component_origin.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/data_bind/data_bind.hpp"
#include "rive/data_bind/data_values/data_type.hpp"
#include "rive/focus_data.hpp"
#include "rive/input/focus_manager.hpp"
#include "rive/input/focusable.hpp"
#include "rive/nested_animation.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/semantic/semantic_data.hpp"
#include "rive/semantic/semantic_manager.hpp"
#include "rive/data_bind/data_bind_path.hpp"
#include "rive/clip_result.hpp"
#include "rive/text/text_input.hpp"
#include "rive/view_model_type.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include <limits>
#include <cassert>

using namespace rive;

namespace
{
std::vector<rcp<ViewModelInstance>> buildVMIList(
    const rcp<ViewModelInstance>& primary,
    const std::vector<rcp<ViewModelInstance>>& globals)
{
    std::vector<rcp<ViewModelInstance>> list;
    list.reserve((primary != nullptr ? 1 : 0) + globals.size());
    if (primary != nullptr)
    {
        list.push_back(primary);
    }
    for (auto& g : globals)
    {
        if (g != nullptr)
        {
            list.push_back(g);
        }
    }
    return list;
}
} // namespace

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;
    // Release our extra refs on the global VMI children (the artboard's
    // m_Objects still holds its own ref for each).
    m_globalViewModelInstances.clear();

    // Scope outlives nested instance swaps; remove from parent FocusManager
    // when the host component is destroyed.
    if (m_focusScope != nullptr && m_focusScope->manager() != nullptr)
    {
        m_focusScope->manager()->removeChild(m_focusScope);
    }
    m_focusScope = nullptr;
}

Core* NestedArtboard::clone() const
{
    NestedArtboard* nestedArtboard =
        static_cast<NestedArtboard*>(NestedArtboardBase::clone());
    nestedArtboard->file(file());
    // Carry the swap-slot flag to clones. It is detected on the SOURCE
    // artboard's host (import populates the source's data binds before
    // onAddedClean)
    if (isArtboardDataBound())
    {
        nestedArtboard->m_hostFlags |=
            NestedArtboardHostFlags::artboardDataBound;
    }
    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->hostOpacity(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);
    // Re-push any authored origin override onto the freshly mounted instance.
    // On initial import the override child may not be linked yet; onAddedClean
    // covers that case.
    applyOriginOverride();
}

void NestedArtboard::applyOriginOverride()
{
    if (m_referencedArtboard == nullptr || !m_referencedArtboard->isInstance())
    {
        return;
    }
    for (auto child : children())
    {
        if (child->is<ComponentOrigin>())
        {
            auto origin = child->as<ComponentOrigin>();
            m_referencedArtboard->originX(origin->originX());
            m_referencedArtboard->originY(origin->originY());
            return;
        }
    }
}

bool NestedArtboard::tryScheduleBindStateful()
{

    if (m_activeViewModelInstance != nullptr && artboardInstance())
    {
        m_hostFlags |= NestedArtboardHostFlags::pendingStatefulBinding;
        return true;
    }
    return false;
}

void NestedArtboard::bindStateful()
{
    m_hostFlags &= ~NestedArtboardHostFlags::pendingStatefulBinding;
    if (artboardInstance() == nullptr)
    {
        return;
    }
    // Active VMI is the local-root binding; append the global VMI children.
    auto list = buildVMIList(ref_rcp(m_activeViewModelInstance),
                             m_globalViewModelInstances);
    artboardInstance()->bindViewModelInstances(std::move(list), m_dataContext);
    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)
{
    // A VM artboard swap means this host is data-bound.
    m_hostFlags |= NestedArtboardHostFlags::artboardDataBound;

    // Resolve the swap target BEFORE tearing anything down. asset == nullptr
    // and propertyValue == -1 is the user explicitly clearing the artboard (a
    // real "set to null"); any OTHER unresolvable id must leave the currently
    // displayed artboard — and its focus tree — untouched, rather than blanking
    // focus for content that stays on screen. findArtboard has no side effects,
    // so resolving it early is safe.
    bool explicitNull = viewModelInstanceArtboard != nullptr &&
                        viewModelInstanceArtboard->asset() == nullptr &&
                        viewModelInstanceArtboard->propertyValue() == -1;
    Artboard* artboard =
        explicitNull
            ? nullptr
            : findArtboard(viewModelInstanceArtboard, parentArtboard(), m_file);
    if (!explicitNull && artboard == nullptr)
    {
        // Unresolved target — keep the outgoing instance and its focus intact.
        return;
    }

    // Detach the outgoing instance's focus tree BEFORE teardown, while every
    // component is still alive: clearing focus runs blur callbacks
    // (FocusData::blurred walks parents/siblings), which must act on live
    // components rather than partially-destroyed ones.
    auto* outgoing = artboardInstance(0);
    if (outgoing != nullptr)
    {
        outgoing->cleanupFocusTree();
        outgoing->cleanupSemanticTree();
    }
    clearDataContext();
    clearNestedAnimations();
    m_boundNestedStateMachine = nullptr;

    if (explicitNull)
    {
        // Only detach a non-owned reference; an owned instance must be
        // destroyed with m_host intact so ~LayoutComponent can clean the
        // hosting artboard's dirty layout set.
        if (m_referencedArtboard != nullptr && m_Instance == nullptr)
        {
            m_referencedArtboard->host(nullptr);
        }
        m_referencedArtboard = nullptr;
        m_Instance = nullptr;
        setActiveViewModelInstance(nullptr, false);
        return;
    }

    if (artboard != nullptr)
    {
        // The host's factory so a databound swap, possibly from another
        // file, keeps the nested content on the hosting instance's session.
        auto artboardInstance = artboard->instance<ArtboardInstance>(
            this->artboard() != nullptr ? this->artboard()->factory()
                                        : nullptr);
        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);

        // Share the parent's focus manager with the swapped-in artboard's
        // state machine BEFORE the focus sync: its listener groups (pointer
        // focus, key/text input) must act on the same focus state Tab
        // traversal uses. The wiring in
        // NestedStateMachine::initializeAnimation is skipped here because the
        // runtime-created bound state machine is unparented.
        auto* parentAb = parentArtboard();
        auto* parentFM =
            parentAb != nullptr ? parentAb->focusManager() : nullptr;
        if (parentFM != nullptr && m_boundNestedStateMachine != nullptr)
        {
            auto* smi = m_boundNestedStateMachine->stateMachineInstance();
            if (smi != nullptr && smi->focusManager() != parentFM)
            {
                smi->setExternalFocusManager(parentFM);
            }
        }
        // Re-home the nested instance's focus tree under the host's scope.
        // setExternalFocusManager above rebuilds the nested tree at the
        // manager root, so scope placement must be the final write.
        syncNestedFocusTree(FocusData::findClosestFocusNode(this));

        // Register the swapped-in instance with the host's semantic manager,
        // reparented under the enclosing SemanticData the same way
        // ArtboardComponentList wires its items
        auto* parentSemanticManager =
            parentAb != nullptr ? parentAb->semanticManager() : nullptr;
        if (parentSemanticManager != nullptr)
        {
            auto parentSemanticNode =
                SemanticData::findClosestSemanticNode(this);
            auto* semanticSmi =
                m_boundNestedStateMachine != nullptr
                    ? m_boundNestedStateMachine->stateMachineInstance()
                    : nullptr;
            if (semanticSmi != nullptr)
            {
                semanticSmi->setExternalSemanticManager(parentSemanticManager,
                                                        parentSemanticNode);
            }
            else if (m_Instance != nullptr)
            {
                // Artboards with no state machine have no instance to hang
                // the external manager off; build the subtree directly.
                m_Instance->buildSemanticTree(parentSemanticManager,
                                              parentSemanticNode);
            }
        }
    }
}

// Focus tree integration for data-bound nested artboards.
//
// When artboardId is bound to a VM artboard property the nested instance can be
// swapped at runtime (e.g. Plain -> Focusable), so its FocusData leaves must
// live in the *parent* StateMachine's FocusManager for Tab order to work across
// the main artboard and nested content. Each data-bound host owns one
// structural m_focusScope (see registerFocusScope) that persists across swaps;
// static nested artboards get no scope and zero extra FocusNode cost.

void NestedArtboard::detectArtboardDataBinding()
{
    // Marks hosts that can receive runtime
    // artboard swaps so a focus scope is allocated later at tree-build time.
    // Only a direct bind of this host's artboardId counts. Match on the
    // bind's target property key: it is static file data, available at
    // import time on the source artboard
    if (isArtboardDataBound())
    {
        return;
    }
    auto* parent = artboard();
    if (parent != nullptr)
    {
        for (auto* dataBind : parent->dataBinds())
        {
            if (dataBind->target() == this &&
                dataBind->propertyKey() ==
                    NestedArtboardBase::artboardIdPropertyKey)
            {
                m_hostFlags |= NestedArtboardHostFlags::artboardDataBound;
                return;
            }
        }
    }
}

void NestedArtboard::registerFocusScope(FocusManager* focusManager,
                                        rcp<FocusNode> parentNode,
                                        bool place)
{
    // No-op for static hosts; data-bound hosts lazily get one persistent scope.
    if (focusManager == nullptr || !isArtboardDataBound())
    {
        return;
    }

    if (m_focusScope == nullptr)
    {
        m_focusScope = FocusNode::makeStructuralScope();
    }

    if (!place && m_focusScope->manager() == focusManager)
    {
        // Ensure-only callers (state machine init, artboard swap) must never
        // move an already-registered scope: the full build pass is the only
        // ordering authority.
        return;
    }

    // Build pass placement, or first registration. During the depth-first
    // build pass every sibling that should precede this scope has already been
    // re-appended by the same walk, so appending yields hierarchy order. A
    // first registration outside a pass is best-effort (appended under the
    // caller's fallback parent) and is normalized by the next build pass.
    focusManager->addChild(std::move(parentNode), m_focusScope);
}

void NestedArtboard::syncNestedFocusTree(rcp<FocusNode> fallbackParent,
                                         bool placeScope,
                                         bool forceRebuild)
{
    auto* parentAb = artboard();
    auto* parentFM = parentAb != nullptr ? parentAb->focusManager() : nullptr;
    if (parentFM == nullptr)
    {
        return;
    }

    // Place the structural scope first — even with no nested instance yet — so
    // a data-bound host whose artboard starts null still has its scope at the
    // authored tab position for a later swap to build under. Placement is a
    // non-destructive move (addChild), so it never clears focus.
    registerFocusScope(parentFM, fallbackParent, placeScope);

    auto* nestedInstance = artboardInstance(0);
    if (nestedInstance == nullptr)
    {
        return;
    }

    // Skip the destructive teardown+rebuild when the subtree already shares
    // this manager and was not just re-wired (forceRebuild): rebuilding an
    // untouched nested instance clears focus resting inside it, while the scope
    // placement above already keeps tab order correct. forceRebuild is set
    // after setExternalFocusManager (which rebuilds at the manager root) or on
    // a swap.
    if (!forceRebuild && nestedInstance->focusManager() == parentFM)
    {
        return;
    }

    nestedInstance->cleanupFocusTree();
    // Under the scope when data-bound, else under fallbackParent (the caller's
    // resolved closest ancestor).
    nestedInstance->buildFocusTree(parentFM,
                                   m_focusScope != nullptr ? m_focusScope
                                                           : fallbackParent);
}

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);
        // Children are linked by now, so an authored origin override child is
        // resolvable; push it onto the mounted instance.
        applyOriginOverride();
    }

    // ViewModelInstance children belong to NestedArtboards that wrap a
    // stateful component Artboard. A single "standard" VMI becomes the active
    // local-root binding (borrowed; the parent Artboard's m_Objects teardown
    // owns its lifetime), and any number of "global" VMIs are appended to the
    // data context passed down to the wrapped artboard.
    for (auto child : children())
    {
        if (!child->is<ViewModelInstance>())
        {
            continue;
        }
        auto vmi = child->as<ViewModelInstance>();
        auto vm = vmi->viewModel();
        auto type = vm != nullptr
                        ? static_cast<ViewModelType>(vm->viewModelType())
                        : ViewModelType::standard;
        m_file->completeViewModelProperties(vmi);
        if (type == ViewModelType::global)
        {
            // The artboard's m_Objects owns the construction ref; take an
            // extra ref so the list outlives any teardown ordering.
            m_globalViewModelInstances.push_back(ref_rcp(vmi));
        }
        else if (m_activeViewModelInstance == nullptr)
        {
            // Borrow the first standard child VMI as the active binding.
            m_activeViewModelInstance = vmi;
            m_ownsActiveVmi = false;
        }
    }
    tryScheduleBindStateful();
    detectArtboardDataBinding();

    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->hostOpacity(renderOpacity());
    }
    // Also flush when the referenced artboard itself is dirty (not just the
    // host). The RenderOpacity branch above writes the host opacity onto the
    // referenced artboard, which marks its own Components dirt. When the nested
    // artboard is paused, advanceComponent short-circuits and never lifts that
    // dirt onto the host, so without this the opacity change would never reach
    // the child's paints. updatePass recomputes render state from the current
    // (frozen) values without advancing animations, preserving pause.
    if (hasDirt(value, ComponentDirt::Components) ||
        (isPaused() &&
         m_referencedArtboard->hasDirt(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)
    {
        return;
    }

    // If we have a stateful ViewModelInstance, bind it (with globals) via
    // the scheduled stateful path.
    if (tryScheduleBindStateful())
    {
        return;
    }

    if (!m_globalViewModelInstances.empty())
    {
        auto list = buildVMIList(nullptr, m_globalViewModelInstances);
        artboardInstance()->bindViewModelInstances(std::move(list), value);
        for (auto& animation : m_NestedAnimations)
        {
            if (animation->is<NestedStateMachine>())
            {
                animation->as<NestedStateMachine>()->dataContext(
                    artboardInstance()->dataContext());
            }
        }
        return;
    }

    // Non-stateful path with no globals: 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->mainViewModelInstance() != 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)
    {
        return;
    }

    // Stateful: local root is the active VMI; append nested globals.
    if (m_activeViewModelInstance != nullptr)
    {
        auto list = buildVMIList(ref_rcp(m_activeViewModelInstance),
                                 m_globalViewModelInstances);
        artboardInstance()->bindViewModelInstances(std::move(list), parent);
        for (auto& animation : m_NestedAnimations)
        {
            if (animation->is<NestedStateMachine>())
            {
                animation->as<NestedStateMachine>()->dataContext(
                    artboardInstance()->dataContext());
            }
        }
        return;
    }

    // Non-stateful with a passed VMI or nested globals: build composite DC.
    if (viewModelInstance != nullptr || !m_globalViewModelInstances.empty())
    {
        auto list = buildVMIList(viewModelInstance, m_globalViewModelInstances);
        artboardInstance()->bindViewModelInstances(std::move(list), parent);
        for (auto& animation : m_NestedAnimations)
        {
            if (animation->is<NestedStateMachine>())
            {
                animation->as<NestedStateMachine>()->dataContext(
                    artboardInstance()->dataContext());
            }
        }
        return;
    }

    // Nothing to merge in — propagate parent context unchanged (legacy
    // passthrough). Binding a null instance would call
    // Artboard::bindViewModelInstance(nullptr, ...), which now triggers
    // unbind(); use internalDataContext to keep the parent context wired.
    artboardInstance()->internalDataContext(parent);
    for (auto& animation : m_NestedAnimations)
    {
        if (animation->is<NestedStateMachine>())
        {
            animation->as<NestedStateMachine>()->dataContext(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 (enums::is_flag_set(m_hostFlags,
                           NestedArtboardHostFlags::pendingStatefulBinding))
    {
        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();
}