#include <game/gamemanager.hpp>
#include <algorithm>

namespace Game {
    void GameManager::run(std::stop_token stopToken) {
        using namespace std::chrono_literals;
        LOG("GameManager thread started");
        Object::Camera::getInstance().setPosition(0.f, 0.f); // Start with camera at (0, 0)

        mLastUpdate = clock::now(); // Get the update

        while (!stopToken.stop_requested()) {
            clock::time_point now = clock::now();
            std::chrono::duration<float> elapsedDt = now - mLastUpdate;
            float seconds = elapsedDt.count();

            const int updatesPerSecond = std::max(1, mTargetUpdatesPerSecond);
            const auto frameDuration = std::chrono::duration<double>(1.0 / static_cast<double>(updatesPerSecond));
            const auto frameStart = std::chrono::steady_clock::now();

            try {
                Input::update(); // Update input states at the start of each frame
                auto entities = State::GameState::getInstance().getEntitiesSnapshot();
                for (auto* entity : entities) {
                    if (entity) {
                        entity->update(seconds);
                    }
                }
            } catch (const std::exception& e) {
                ERROR("Exception in GameManager thread: " << e.what());
            }

            mLastUpdate = now;

            const auto elapsed = std::chrono::steady_clock::now() - frameStart;
            const auto remaining = frameDuration - elapsed;
            if (remaining > 0s) {
                std::this_thread::sleep_for(remaining);
            }
        }
    }

    // Statics
    std::unordered_map<std::string, std::string> GameManager::mSharedStrings;

    void GameManager::setSharedData(const std::string& key, std::string data) {
        mSharedStrings[key] = std::move(data);
    }

    std::string GameManager::getSharedData(const std::string& key) {
        auto it = mSharedStrings.find(key);
        if (it != mSharedStrings.end()) {
            return it->second;
        }
        return ""; // Key not found
    }

    void GameManager::removeSharedData(const std::string& key) {
        mSharedStrings.erase(key);
    }
}