#include "Scene.h"
#include <algorithm>  // for std::find_if

namespace OX
{
    GameObject *Scene::createRootObject(const std::string &name)
    {
        auto go = std::make_unique<GameObject>(name);
        GameObject *ptr = go.get();
        registerByTag(ptr);
        m_roots.push_back(std::move(go));
        return ptr;
    }

    bool Scene::removeRootObject(GameObject *go)
    {
        auto it = std::ranges::find_if(m_roots,
                                       [go](const std::unique_ptr<GameObject> &u) { return u.get() == go; }
        );

        if (it == m_roots.end())
            return false;

        unregisterByTag(go);
        m_roots.erase(it);
        return true;
    }

    const std::vector<std::unique_ptr<GameObject> > &Scene::roots() const
    {
        return m_roots;
    }

    GameObject *Scene::findByTag(const std::string &tag) const
    {
        auto it = m_tagIndex.find(tag);
        return (it != m_tagIndex.end()) ? it->second : nullptr;
    }

    void Scene::registerByTag(GameObject *go)
    {
        if (auto tc = go->GetComponent<TagComponent>()) {
            m_tagIndex[tc->name] = go;
        }
        for (auto &child: go->children()) {
            registerByTag(child.get());
        }
    }

    void Scene::unregisterByTag(GameObject *go)
    {
        if (auto tc = go->GetComponent<TagComponent>()) {
            m_tagIndex.erase(tc->name);
        }
        for (auto &child: go->children()) {
            unregisterByTag(child.get());
        }
    }
} // namespace OX
