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

std::unique_ptr<Artboard> Artboard::instance() const {
    std::unique_ptr<Artboard> artboardClone(clone()->as<Artboard>());

    artboardClone->m_FrameOrigin = m_FrameOrigin;

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

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