#include "rive/artboard.hpp"
#include "rive/backboard.hpp"
#include "rive/animation/animation.hpp"
#include "rive/dependency_sorter.hpp"
#include "rive/draw_rules.hpp"
#include "rive/draw_target.hpp"
#include "rive/draw_target_placement.hpp"
#include "rive/drawable.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/node.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/animation/state_machine_instance.hpp"

#include <stack>
#include <unordered_map>

using namespace rive;

Artboard::~Artboard() {
    for (auto object : m_Objects) {
        // First object is artboard
        if (object == this) {
            continue;
        }
        delete object;
    }

    // Instances reference back to the original artboard's animations and state
    // machines, so don't delete them here, they'll get cleaned up when the
    // source is deleted.
    if (!m_IsInstance) {
        for (auto object : m_Animations) {
            delete object;
        }
        for (auto object : m_StateMachines) {
            delete object;
        }
    }
}

static bool canContinue(StatusCode code) {
    // We currently only cease loading on invalid object.
    return code != StatusCode::InvalidObject;
}

StatusCode Artboard::initialize() {
    StatusCode code;

    m_BackgroundPath = makeCommandPath(PathSpace::Neither);
    m_ClipPath = makeCommandPath(PathSpace::Neither);

    // onAddedDirty guarantees that all objects are now available so they can be
    // looked up by index/id. This is where nodes find their parents, but they
    // can't assume that their parent's parent will have resolved yet.
    for (auto object : m_Objects) {
        if (object == nullptr) {
            // objects can be null if they were not understood by this runtime.
            continue;
        }
        if (!canContinue(code = object->onAddedDirty(this))) {
            return code;
        }
    }

    for (auto object : m_Animations) {
        if (!canContinue(code = object->onAddedDirty(this))) {
            return code;
        }
    }

    for (auto object : m_StateMachines) {
        if (!canContinue(code = object->onAddedDirty(this))) {
            return code;
        }
    }
    // Store a map of the drawRules to make it easier to lookup the matching
    // rule for a transform component.
    std::unordered_map<Core*, DrawRules*> componentDrawRules;

    // onAddedClean is called when all individually referenced components have
    // been found and so components can look at other components' references and
    // assume that they have resolved too. This is where the whole hierarchy is
    // linked up and we can traverse it to find other references (my parent's
    // parent should be type X can be checked now).
    for (auto object : m_Objects) {
        if (object == nullptr) {
            continue;
        }
        if (!canContinue(code = object->onAddedClean(this))) {
            return code;
        }
        switch (object->coreType()) {
            case DrawRulesBase::typeKey: {
                DrawRules* rules = reinterpret_cast<DrawRules*>(object);
                Core* component = resolve(rules->parentId());
                if (component != nullptr) {
                    componentDrawRules[component] = rules;
                } else {
                    fprintf(stderr,
                            "Artboard::initialize - Draw rule targets missing "
                            "component width id %d\n",
                            rules->parentId());
                }
                break;
            }
            case NestedArtboardBase::typeKey:
                m_NestedArtboards.push_back(object->as<NestedArtboard>());
                break;
        }
    }

    for (auto object : m_Animations) {
        if (!canContinue(code = object->onAddedClean(this))) {
            return code;
        }
    }

    for (auto object : m_StateMachines) {
        if (!canContinue(code = object->onAddedClean(this))) {
            return code;
        }
    }

    // Multi-level references have been built up, now we can
    // actually mark what's dependent on what.
    for (auto object : m_Objects) {
        if (object == nullptr) {
            continue;
        }
        if (object->is<Component>()) {
            object->as<Component>()->buildDependencies();
        }
        if (object->is<Drawable>()) {
            Drawable* drawable = object->as<Drawable>();
            m_Drawables.push_back(drawable);

            for (ContainerComponent* parent = drawable; parent != nullptr;
                 parent = parent->parent()) {
                auto itr = componentDrawRules.find(parent);
                if (itr != componentDrawRules.end()) {
                    drawable->flattenedDrawRules = itr->second;
                    break;
                }
            }
        }
    }

    sortDependencies();

    DrawTarget root;
    // Build up the draw order. Look for draw targets and build
    // their dependencies.
    for (auto object : m_Objects) {
        if (object == nullptr) {
            continue;
        }
        if (object->is<DrawTarget>()) {
            DrawTarget* target = object->as<DrawTarget>();
            root.addDependent(target);

            auto dependentRules = target->drawable()->flattenedDrawRules;
            if (dependentRules != nullptr) {
                // Because we don't store targets on rules, we need
                // to find the targets that belong to this rule
                // here.
                for (auto object : m_Objects) {
                    if (object != nullptr && object->is<DrawTarget>()) {
                        DrawTarget* dependentTarget = object->as<DrawTarget>();
                        if (dependentTarget->parent() == dependentRules) {
                            dependentTarget->addDependent(target);
                        }
                    }
                }
            }
        }
    }
    DependencySorter sorter;
    std::vector<Component*> drawTargetOrder;
    sorter.sort(&root, drawTargetOrder);
    auto itr = drawTargetOrder.begin();
    itr++;
    while (itr != drawTargetOrder.end()) {
        m_DrawTargets.push_back(reinterpret_cast<DrawTarget*>(*itr++));
    }

    return StatusCode::Ok;
}

void Artboard::sortDrawOrder() {
    for (auto target : m_DrawTargets) {
        target->first = target->last = nullptr;
    }

    m_FirstDrawable = nullptr;
    Drawable* lastDrawable = nullptr;
    for (auto drawable : m_Drawables) {
        auto rules = drawable->flattenedDrawRules;
        if (rules != nullptr && rules->activeTarget() != nullptr) {

            auto target = rules->activeTarget();
            if (target->first == nullptr) {
                target->first = target->last = drawable;
                drawable->prev = drawable->next = nullptr;
            } else {
                target->last->next = drawable;
                drawable->prev = target->last;
                target->last = drawable;
                drawable->next = nullptr;
            }
        } else {
            drawable->prev = lastDrawable;
            drawable->next = nullptr;
            if (lastDrawable == nullptr) {
                lastDrawable = m_FirstDrawable = drawable;
            } else {
                lastDrawable->next = drawable;
                lastDrawable = drawable;
            }
        }
    }

    for (auto rule : m_DrawTargets) {
        if (rule->first == nullptr) {
            continue;
        }
        auto targetDrawable = rule->drawable();
        switch (rule->placement()) {
            case DrawTargetPlacement::before: {
                if (targetDrawable->prev != nullptr) {
                    targetDrawable->prev->next = rule->first;
                    rule->first->prev = targetDrawable->prev;
                }
                if (targetDrawable == m_FirstDrawable) {
                    m_FirstDrawable = rule->first;
                }
                targetDrawable->prev = rule->last;
                rule->last->next = targetDrawable;
                break;
            }
            case DrawTargetPlacement::after: {
                if (targetDrawable->next != nullptr) {
                    targetDrawable->next->prev = rule->last;
                    rule->last->next = targetDrawable->next;
                }
                if (targetDrawable == lastDrawable) {
                    lastDrawable = rule->last;
                }
                targetDrawable->next = rule->first;
                rule->first->prev = targetDrawable;
                break;
            }
        }
    }

    m_FirstDrawable = lastDrawable;
}

void Artboard::sortDependencies() {
    DependencySorter sorter;
    sorter.sort(this, m_DependencyOrder);
    unsigned int graphOrder = 0;
    for (auto component : m_DependencyOrder) {
        component->m_GraphOrder = graphOrder++;
    }
    m_Dirt |= ComponentDirt::Components;
}

void Artboard::addObject(Core* object) { m_Objects.push_back(object); }

void Artboard::addAnimation(LinearAnimation* object) { m_Animations.push_back(object); }

void Artboard::addStateMachine(StateMachine* object) { m_StateMachines.push_back(object); }

void Artboard::addNestedArtboard(NestedArtboard* artboard) {
    m_NestedArtboards.push_back(artboard);
}

Core* Artboard::resolve(uint32_t id) const {
    if (id < 0 || id >= static_cast<int>(m_Objects.size())) {
        return nullptr;
    }
    return m_Objects[id];
}

uint32_t Artboard::idOf(Core* object) const {
    auto it = std::find(m_Objects.begin(), m_Objects.end(), object);

    if (it != m_Objects.end()) {
        return it - m_Objects.begin();
    } else {
        return 0;
    }
}

void Artboard::onComponentDirty(Component* component) {
    m_Dirt |= ComponentDirt::Components;

    /// If the order of the component is less than the current dirt
    /// depth, update the dirt depth so that the update loop can break
    /// out early and re-run (something up the tree is dirty).
    if (component->graphOrder() < m_DirtDepth) {
        m_DirtDepth = component->graphOrder();
    }
}

void Artboard::onDirty(ComponentDirt dirt) { m_Dirt |= ComponentDirt::Components; }

void Artboard::update(ComponentDirt value) {
    if (hasDirt(value, ComponentDirt::DrawOrder)) {
        sortDrawOrder();
    }
    if (hasDirt(value, ComponentDirt::Path)) {
        m_ClipPath->reset();
        if (m_FrameOrigin) {
            m_ClipPath->addRect(0.0f, 0.0f, width(), height());
        } else {
            m_ClipPath->addRect(-width() * originX(), -height() * originY(), width(), height());
        }
        m_BackgroundPath->addRect(-width() * originX(), -height() * originY(), width(), height());
    }
}

bool Artboard::updateComponents() {
    if (hasDirt(ComponentDirt::Components)) {
        const int maxSteps = 100;
        int step = 0;
        auto count = m_DependencyOrder.size();
        while (hasDirt(ComponentDirt::Components) && step < maxSteps) {
            m_Dirt = m_Dirt & ~ComponentDirt::Components;

            // Track dirt depth here so that if something else marks
            // dirty, we restart.
            for (unsigned int i = 0; i < count; i++) {
                auto component = m_DependencyOrder[i];
                m_DirtDepth = i;
                auto d = component->m_Dirt;
                if (d == ComponentDirt::None) {
                    continue;
                }
                component->m_Dirt = ComponentDirt::None;
                component->update(d);

                // If the update changed the dirt depth by adding dirt
                // to something before us (in the DAG), early out and
                // re-run the update.
                if (m_DirtDepth < i) {
                    // We put this in here just to know if we need to
                    // keep this around...
                    assert(false);
                    break;
                }
            }
            step++;
        }
        return true;
    }
    return false;
}

bool Artboard::advance(double elapsedSeconds) {
    for (auto nestedArtboard : m_NestedArtboards) {
        nestedArtboard->advance(elapsedSeconds);
    }
    return updateComponents();
}

Core* Artboard::hitTest(HitInfo* hinfo, const Mat2D* xform) {
    if (clip()) {
        // TODO: can we get the rawpath for the clip?
    }

    auto mx = xform ? *xform : Mat2D();
    if (m_FrameOrigin) {
        mx *= Mat2D::fromTranslate(width() * originX(), height() * originY());
    }

    Drawable* last = m_FirstDrawable;
    if (last) {
        // walk to the end, so we can visit in reverse-order
        while (last->prev) {
            last = last->prev;
        }
    }
    for (auto drawable = last; drawable; drawable = drawable->next) {
        if (drawable->isHidden()) {
            continue;
        }
        if (auto c = drawable->hitTest(hinfo, mx)) {
            return c;
        }
    }

    // TODO: should we hit-test the background?

    return nullptr;
}

void Artboard::draw(Renderer* renderer, DrawOption option) {
    renderer->save();
    if (clip()) {
        renderer->clipPath(m_ClipPath->renderPath());
    }

    if (m_FrameOrigin) {
        Mat2D artboardTransform;
        artboardTransform[4] = width() * originX();
        artboardTransform[5] = height() * originY();
        renderer->transform(artboardTransform);
    }

    if (option != DrawOption::kHideBG) {
        for (auto shapePaint : m_ShapePaints) {
            shapePaint->draw(renderer, backgroundPath());
        }
    }

    if (option != DrawOption::kHideFG) {
        for (auto drawable = m_FirstDrawable; drawable != nullptr; drawable = drawable->prev) {
            if (drawable->isHidden()) {
                continue;
            }
            drawable->draw(renderer);
        }
    }

    renderer->restore();
}

AABB Artboard::bounds() const { return AABB(0.0f, 0.0f, width(), height()); }

bool Artboard::isTranslucent(const LinearAnimation* anim) const {
    // For now we're conservative/lazy -- if we see that any of our paints are
    // animated we assume that might make it non-opaque, so we early out
    for (const auto obj : anim->m_KeyedObjects) {
        const auto ptr = this->resolve(obj->objectId());
        for (const auto sp : m_ShapePaints) {
            if (ptr == sp) {
                return true;
            }
        }
    }

    // If we get here, we have no animations, so just check our paints for
    // opacity

    for (const auto sp : m_ShapePaints) {
        if (!sp->isTranslucent()) {
            return false; // one opaque fill is sufficient to be opaque
        }
    }
    return true;
}

LinearAnimation* Artboard::firstAnimation() const {
    if (m_Animations.empty()) {
        return nullptr;
    }
    return m_Animations.front();
}

LinearAnimation* Artboard::animation(std::string name) const {
    for (auto animation : m_Animations) {
        if (animation->name() == name) {
            return animation;
        }
    }
    return nullptr;
}

LinearAnimation* Artboard::animation(size_t index) const {
    if (index >= m_Animations.size()) {
        return nullptr;
    }
    return m_Animations[index];
}

StateMachine* Artboard::firstStateMachine() const {
    if (m_StateMachines.empty()) {
        return nullptr;
    }
    return m_StateMachines.front();
}

StateMachine* Artboard::stateMachine(std::string name) const {
    for (auto machine : m_StateMachines) {
        if (machine->name() == name) {
            return machine;
        }
    }
    return nullptr;
}

StateMachine* Artboard::stateMachine(size_t index) const {
    if (index >= m_StateMachines.size()) {
        return nullptr;
    }
    return m_StateMachines[index];
}

StateMachineInstance* Artboard::stateMachineInstance(std::string name) {
    StateMachine* machine = stateMachine(name);
    if (machine != nullptr) {
        return new StateMachineInstance(machine, this);
    }
    return nullptr;
}

StateMachineInstance* Artboard::stateMachineInstance(size_t index) {
    StateMachine* machine = stateMachine(index);
    if (machine != nullptr) {
        return new StateMachineInstance(machine, this);
    }
    return nullptr;
}

Artboard* Artboard::instance() const {
    auto artboardClone = clone()->as<Artboard>();
    artboardClone->m_FrameOrigin = m_FrameOrigin;

    std::vector<Core*>& cloneObjects = artboardClone->m_Objects;
    cloneObjects.push_back(artboardClone);

    // Skip first object (artboard).
    auto itr = m_Objects.begin();
    while (++itr != m_Objects.end()) {
        auto object = *itr;
        cloneObjects.push_back(object == nullptr ? nullptr : object->clone());
    }

    for (auto animation : m_Animations) {
        artboardClone->m_Animations.push_back(animation);
    }
    for (auto stateMachine : m_StateMachines) {
        artboardClone->m_StateMachines.push_back(stateMachine);
    }

    if (artboardClone->initialize() != StatusCode::Ok) {
        delete artboardClone;
        artboardClone = nullptr;
    } else {
        artboardClone->m_IsInstance = true;
    }

    return artboardClone;
}

void Artboard::frameOrigin(bool value) {
    if (value == m_FrameOrigin) {
        return;
    }
    m_FrameOrigin = value;
    addDirt(ComponentDirt::Path);
}

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

    StatusCode result = Super::import(importStack);
    if (result == StatusCode::Ok) {
        backboardImporter->addArtboard(this);
    } else {
        backboardImporter->addMissingArtboard();
    }
    return result;
}

void Artboard::postPointerEvent(const PointerEvent& evt) {
    if (true) {
        static bool gButtonIsDown;

        switch (evt.m_Type) {
            case PointerEventType::down:
                assert(!gButtonIsDown);
                gButtonIsDown = true;
                break;
            case PointerEventType::up:
                assert(gButtonIsDown);
                gButtonIsDown = false;
                break;
            default:
                break;
        }

#if 0
        const char* typeNames[] = {
            "down", "move", "up  ",
        };
        printf("pointer: %s [%g %g] %s\n",
               typeNames[(int)evt.m_Type],
               evt.m_Position.x(), evt.m_Position.y(),
               gButtonIsDown ? "DOWN" : "UP");
#endif
    }

#if 0
    // TESTING ONLY
    // This is the sort of message that the Artboard would post...
    // e.g. if the down AND up were inside the same clickable shape.
    if (evt.m_Type == PointerEventType::up) {
        Message msg;
        msg.m_Str = "ClickEvent";
        this->testing_only_enque_message(msg);
    }
#endif
}

void Artboard::testing_only_enque_message(const Message& msg) { m_MessageQueue.push(msg); }

bool Artboard::hasMessages() const { return !m_MessageQueue.empty(); }

bool Artboard::nextMessage(Message* msg) {
    if (m_MessageQueue.empty()) {
        return false;
    } else {
        *msg = m_MessageQueue.front();
        m_MessageQueue.pop();
        return true;
    }
}
