
#pragma once

#include <vector>
#include <memory>
#include <unordered_map>
#include <string>

#include "GameObject.h"
#include "Components/TagComponent.h"
#include "systems/MACROS.h"

namespace OX
{
    class Scene
    {
    public:
        Scene() = default;

        ~Scene() = default;

        /// Create a new root GameObject. Returns the raw pointer.
        GameObject *createRootObject(const std::string &name = "");

        /// Remove (and destroy) a root object by pointer.
        bool removeRootObject(GameObject *go);

        /// Access all root objects.
        const std::vector<std::unique_ptr<GameObject> > &roots() const;

        /// O(1)
        GameObject *findByTag(const std::string &tag) const;

        /// Must be called whenever a GameObject’s tag is set or changed.
        void registerByTag(GameObject *go);

        /// Must be called before a GameObject is destroyed or its tag changes.
        void unregisterByTag(GameObject *go);

    private:
        std::vector<std::unique_ptr<GameObject> > m_roots;
        std::unordered_map<std::string, GameObject *> m_tagIndex;
    };
} // namespace OX
