//
// Created by spenc on 5/14/2025.
//

#include "Core.h"

#include "systems/MACROS.h"
#include "systems/AssetManager.h"
#include "systems/assets/Texture2D.h"

namespace OX
{
    void Core::AddLayer(std::unique_ptr<Layer> layer)
    {
        Logger::LogDebug("Added Layer: '%s'", layer->GetName().c_str());
        m_layers.emplace_back(std::move(layer));
    }

    void Core::Init()
    {
        Logger::LogInfo("Initializing Core...");

        if (!window.Init(m_name, 1280, 720))
            return;

        OX_ENSURE(!m_layers.empty(), "No Layers Attached");

        for (const auto &layer: m_layers) {
            layer->Init(*this);
        }


        std::string layerTitle;
        for (size_t i = 0; i < m_layers.size(); ++i) {
            if (i > 0)
                layerTitle += " - ";
            layerTitle += m_layers[i]->GetName();
        }


        std::string fullTitle = layerTitle + " - " + m_name;
        window.SetWindowTitle(fullTitle);
        renderer.Init(800, 600);

        Logger::LogOk("Core Initialization Complete.");

        AssetManager::Init("C:/Users/spenc/OneDrive/Desktop/OnyxProject");
    }


    void Core::Run()
    {
        m_running = true;

        while (!window.ShouldClose()) {
            Profiler::BeginFrame(); {
                OX_PROFILE_LABEL("Frame");
                Update();
                window.BeginFrame();

                Draw();
                window.EndFrame();
            }
            Profiler::EndFrame();
        }
    }

    void Core::Update()
    {
        OX_PROFILE_FUNCTION();

        AssetManager::Tick();

        for (auto &layer: m_layers) {
            layer->Update(*this);
        }
    }


    void Core::Draw()
    {
        OX_PROFILE_FUNCTION();

        Camera2D cam(0, 800, 0, 600);
        renderer.BeginScene(cam);

        if (auto asset = AssetManager::Get("res://Assets/tile_001.png"); asset && asset->GetTypeName() == "texture2D") {
            const auto tex = std::static_pointer_cast<Texture2D>(asset);
            renderer.DrawSprite({tex->GetID(), {0, 0}, {64, 64}});
        }


        renderer.EndScene();


        for (auto &layer: m_layers) {
            layer->Draw(*this);
        }
    }

    void Core::Shutdown()
    {
        Logger::LogDebug("Shutting down Core...");


        for (auto &layer: m_layers) {
            Logger::LogDebug("Shutting down Layer: '%s'", layer->GetName().c_str());
            layer->Shutdown(*this);
            Logger::LogOk("'%s' Shutdown Complete", layer->GetName().c_str());
        }

        m_layers.clear();

        AssetManager::Shutdown();
        Logger::LogOk("AssetManager Shutdown Complete.");

        window.Shutdown();

        Logger::LogOk("Core Shutdown Complete.");
    }
}
