#ifndef _RIVE_ARTBOARD_HPP_
#define _RIVE_ARTBOARD_HPP_

#include "rive/animation/linear_animation.hpp"
#include "rive/animation/state_machine.hpp"
#include "rive/core_context.hpp"
#include "rive/generated/artboard_base.hpp"
#include "rive/hit_info.hpp"
#include "rive/message.hpp"
#include "rive/math/aabb.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/shape_paint_container.hpp"

#include <queue>
#include <vector>

namespace rive {
    class File;
    class Drawable;
    class Factory;
    class Node;
    class DrawTarget;
    class ArtboardImporter;
    class NestedArtboard;
    class ArtboardInstance;
    class LinearAnimationInstance;
    class StateMachineInstance;

    class Artboard : public ArtboardBase, public CoreContext, public ShapePaintContainer {
        friend class File;
        friend class ArtboardImporter;
        friend class Component;

    protected:
        void deleteObjects();   // call from destructors
    
        // these are owned if we are not an instance, but are not owned
        // if we are an instance.
        std::vector<LinearAnimation*> m_Animations;
        std::vector<StateMachine*> m_StateMachines;

    private:
        std::vector<Core*> m_Objects;
        std::vector<Component*> m_DependencyOrder;
        std::vector<Drawable*> m_Drawables;
        std::vector<DrawTarget*> m_DrawTargets;
        std::vector<NestedArtboard*> m_NestedArtboards;

        unsigned int m_DirtDepth = 0;
        std::unique_ptr<CommandPath> m_BackgroundPath;
        std::unique_ptr<CommandPath> m_ClipPath;
        Factory* m_Factory = nullptr;
        Drawable* m_FirstDrawable = nullptr;
        bool m_FrameOrigin = true;

        std::queue<Message> m_MessageQueue;

        void sortDependencies();
        void sortDrawOrder();

        Artboard* getArtboard() override { return this; }

#ifdef TESTING
    public:
        Artboard(Factory* factory) : m_Factory(factory) {}
#endif
        void addObject(Core* object);
        void addAnimation(LinearAnimation* object);
        void addStateMachine(StateMachine* object);
        void addNestedArtboard(NestedArtboard* object);

        void testing_only_enque_message(const Message&);

    public:
        Artboard() {}
        ~Artboard() override;
        StatusCode initialize();

        Core* resolve(uint32_t id) const override;


        /// Find the id of a component in the artboard the object in the artboard. The artboard
        /// itself has id 0 so we use that as a flag for not found.
        uint32_t idOf(Core* object) const;

        Factory* factory() const { return m_Factory; }

        // EXPERIMENTAL -- for internal testing only for now.
        // DO NOT RELY ON THIS as it may change/disappear in the future.
        Core* hitTest(HitInfo*, const Mat2D* = nullptr);

        void onComponentDirty(Component* component);

        /// Update components that depend on each other in DAG order.
        bool updateComponents();
        void update(ComponentDirt value) override;
        void onDirty(ComponentDirt dirt) override;

        bool advance(double elapsedSeconds);

        // Returns true iff calling popMessage() will return true.
        bool hasMessages() const;

        // If there are any queued messages...
        //   copies the first message into msg parameter
        //   removes that message from the queue
        //   returns true
        // else
        //   ignores msg parameter
        //   returns false
        //
        bool nextMessage(Message* msg);

        enum class DrawOption {
            kNormal,
            kHideBG,
            kHideFG,
        };
        void draw(Renderer* renderer, DrawOption = DrawOption::kNormal);

        CommandPath* clipPath() const { return m_ClipPath.get(); }
        CommandPath* backgroundPath() const { return m_BackgroundPath.get(); }

        const std::vector<Core*>& objects() const { return m_Objects; }

        AABB bounds() const;
        bool isTranslucent(const LinearAnimation*) const;
        bool isTranslucent(const LinearAnimationInstance*) const;

        template <typename T = Component> T* find(std::string name) {
            for (auto object : m_Objects) {
                if (object != nullptr && object->is<T>() && object->as<T>()->name() == name) {
                    return reinterpret_cast<T*>(object);
                }
            }
            return nullptr;
        }

        size_t animationCount() const { return m_Animations.size(); }
        std::string animationNameAt(size_t index) const;

        size_t stateMachineCount() const { return m_StateMachines.size(); }
        std::string stateMachineNameAt(size_t index) const;

        LinearAnimation* firstAnimation() const;
        LinearAnimation* animation(std::string name) const;
        LinearAnimation* animation(size_t index) const;

        StateMachine* firstStateMachine() const;
        StateMachine* stateMachine(std::string name) const;
        StateMachine* stateMachine(size_t index) const;

        /// Make an instance of this artboard, must be explictly deleted when no
        /// longer needed.
        // Deprecated...
        std::unique_ptr<ArtboardInstance> instance() const;

        /// Returns true if the artboard is an instance of another
        virtual bool isInstance() const { return false; }

        /// Returns true when the artboard will shift the origin from the top
        /// left to the relative width/height of the artboard itself. This is
        /// what the editor does visually when you change the origin value to
        /// give context as to where the origin lies within the framed bounds.
        bool frameOrigin() const { return m_FrameOrigin; }
        /// When composing multiple artboards together in a common world-space,
        /// it may be desireable to have them share the same space regardless of
        /// origin offset from the bounding artboard. Set frameOrigin to false
        /// to move the bounds relative to the origin instead of the origin
        /// relative to the bounds.
        void frameOrigin(bool value);

        StatusCode import(ImportStack& importStack) override;
    };

    class ArtboardInstance : public Artboard {
    public:
        ArtboardInstance() {}
        ~ArtboardInstance() override;

        bool isInstance() const override { return true; }

        std::unique_ptr<LinearAnimationInstance> animationAt(size_t index);
        std::unique_ptr<LinearAnimationInstance> animationNamed(std::string name);

        std::unique_ptr<StateMachineInstance> stateMachineAt(size_t index);
        std::unique_ptr<StateMachineInstance> stateMachineNamed(std::string name);
    };
} // namespace rive

#endif
