#include "rive/nested_artboard.hpp"
#include "rive/artboard.hpp"
#include "rive/backboard.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/nested_animation.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include <cassert>

using namespace rive;

NestedArtboard::NestedArtboard() {}
NestedArtboard::~NestedArtboard() {}

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

void NestedArtboard::nest(Artboard* artboard) {
    assert(artboard != nullptr);

    m_Artboard = artboard;
    m_Artboard->frameOrigin(false);
    m_Instance = nullptr;
    if (artboard->isInstance()) {
        m_Instance.reset(static_cast<ArtboardInstance*>(artboard)); // take ownership
    }
    m_Artboard->advance(0.0f);
}

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

void NestedArtboard::draw(Renderer* renderer) {
    if (m_Artboard == nullptr) {
        return;
    }
    if (!clip(renderer)) {
        // We didn't clip, so make sure to save as we'll be doing some
        // transformations.
        renderer->save();
    }
    renderer->transform(worldTransform());
    m_Artboard->draw(renderer);
    renderer->restore();
}

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

StatusCode NestedArtboard::import(ImportStack& importStack) {
    auto backboardImporter = importStack.latest<BackboardImporter>(Backboard::typeKey);
    if (backboardImporter == nullptr) {
        return StatusCode::MissingObject;
    }
    backboardImporter->addNestedArtboard(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_Artboard == nullptr || m_Artboard == m_Instance.get());

    if (m_Instance) {
        for (auto animation : m_NestedAnimations) {
            animation->initializeAnimation(m_Instance.get());
        }
    }
    return Super::onAddedClean(context);
}

bool NestedArtboard::advance(float elapsedSeconds) {
    if (m_Artboard == nullptr) {
        return false;
    }
    for (auto animation : m_NestedAnimations) {
        animation->advance(elapsedSeconds);
    }
    return m_Artboard->advance(elapsedSeconds);
}

void NestedArtboard::update(ComponentDirt value) {
    Super::update(value);
    if (hasDirt(value, ComponentDirt::WorldTransform) && m_Artboard != nullptr) {
        m_Artboard->opacity(renderOpacity());
    }
}

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

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

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

    *local = toMountedArtboard * world;

    return true;
}