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

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->viewModelInstance())
        {
            bindViewModelInstance(
                viewModelInstanceArtboard->viewModelInstance(),
                m_dataContext);
        }
        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);
            break;
        }
    }

    return Super::onAddedClean(context);
}

void NestedArtboard::update(ComponentDirt value)
{
    Super::update(value);
    if (m_referencedArtboard == nullptr)
    {
        return;
    }
    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::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 (m_statefulViewModelInstance != nullptr)
        {
            artboardInstance()->bindViewModelInstance(
                m_statefulViewModelInstance,
                value);
            for (auto& animation : m_NestedAnimations)
            {
                if (animation->is<NestedStateMachine>())
                {
                    animation->as<NestedStateMachine>()->dataContext(
                        artboardInstance()->dataContext());
                }
            }
            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)
{
    auto instance = artboardInstance(0);
    if (instance)
    {
        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)
    {
        artboardInstance()->bindViewModelInstance(viewModelInstance, parent);
        for (auto& animation : m_NestedAnimations)
        {
            if (animation->is<NestedStateMachine>())
            {
                animation->as<NestedStateMachine>()->dataContext(
                    artboardInstance()->dataContext());
            }
        }
    }
}

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

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

bool NestedArtboard::keyInput(Key value,
                              KeyModifiers modifiers,
                              bool isPressed,
                              bool isRepeat)
{
    if (m_Instance == nullptr)
    {
        return false;
    }
    return m_Instance->keyInput(static_cast<uint16_t>(value),
                                static_cast<uint8_t>(modifiers),
                                isPressed,
                                isRepeat);
}

bool NestedArtboard::textInput(const std::string& text)
{
    if (m_Instance == nullptr)
    {
        return false;
    }
    return m_Instance->textInput(text);
}