//
// Created by sebastian on 29.07.26.
//

#include "GameLayer.h"

#include <format>
#include <iostream>
#include <ostream>

#include "ecs/standardComponents/MeshComponent.h"
#include "ecs/standardComponents/TransformComponent.h"
#include "renderer/MeshRenderer.h"
#include "renderer/MeshRenderSystem.h"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>

#include "core/animation/components/BlockingAnimationComponent.h"
#include "core/audio/SoundSource.h"
#include "core/audio/ecs/BlockingSoundComponent.h"
#include "core/audio/ecs/PlaySoundComponent.h"
#include "GLFW/glfw3.h"
using namespace engine;
void GameLayer::onAttachImpl() {
    m_renderState.depthTesting = false;
    m_renderState.backfaceCulling = false;

    m_renderer = std::make_unique<engine::MeshRenderer>();

    m_cameraController = std::make_unique<engine::CameraController>(getInputStack(), getInputContext());


    std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModels = std::unordered_map<std::string, std::shared_ptr<engine::Model>>();
    pieceModels["Red"] = m_assetManager.getModel("pawn_red");
    pieceModels["Blue"] = m_assetManager.getModel("pawn_blue");
    pieceModels["Green"] = m_assetManager.getModel("pawn_green");
    pieceModels["Yellow"] = m_assetManager.getModel("pawn_yellow");

    std::unordered_map<std::string, std::shared_ptr<engine::audio::SoundBuffer>> pieceSounds;
    pieceSounds["step"] = m_assetManager.getSound("pawn_step");

    auto boardLayout = ludo::BoardLayout(m_assetManager.getModel("gameboard"));

    ludo::GameController::LudoGameControllerContext context = {
        .gameMode = m_gameMode,
        .registry = m_entityRegistry,
        .camera = *m_camera,
        .boardModel = m_assetManager.getModel("gameboard"),
        .eventBus = m_eventBus,
        .animationEventBus = getAnimationEventBus(),
        .pieceModels = pieceModels,
        .pieceSounds = pieceSounds,
        .localPlayer = 0
    };
    this->m_GameController = std::move( ludo::GameController::LudoGameController::create(context));

}

void GameLayer::onDetachImpl() {

}

void GameLayer::renderHud() {
    ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
    ImGui::Begin("Ludo", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize);

    auto currentPlayerColor = m_GameController->getPresentationGameState().getCurrentPlayerColor();
    int currentDiceValue = m_GameController->getPresentationGameState().getDiceValue();
    ImGui::Text("Am Zug: %s", toString(currentPlayerColor).data());
    ImGui::Text("Wuerfel: %d", currentDiceValue);

    ImGui::BeginDisabled(m_GameController->isBlocking() || !m_GameController->getPresentationGameState().isDiceRollEnabled());
    if (ImGui::Button("Wuerfeln")) {
        m_gameMode->sendCommand(ludo::RollDiceCommand{m_GameController->getLocalPlayer()});
    }
    //
    // if (!m_lastEventMessage.empty()) ImGui::Text("%s", m_lastEventMessage.c_str());

    ImGui::EndDisabled();

    ImGui::End();

}


void GameLayer::onUpdate(float deltaTime) {
    Layer::onUpdate(deltaTime);
    m_cameraController->update(getKeyboard(), *m_camera, deltaTime);

    m_GameController->update(deltaTime, getMouse(), getKeyboard());
}

void GameLayer::onRender() {
    m_renderQueue.clear();

    MeshRenderSystem meshRenderSystem;
    meshRenderSystem.update(m_entityRegistry, m_renderQueue);
    m_renderer->render(m_renderQueue, *m_camera, *m_pointLight);

    renderHud();
}
