//
// 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/audio/SoundSource.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());
    m_piecePresenter.spawnPieces(m_gameMode->getState());
}

void GameLayer::onDetachImpl() {

}

void GameLayer::renderHud() {
    const auto& state = m_gameMode->getState();
    bool isMyTurn = m_gameMode->getCurrentPlayer() == m_localPlayer;

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

    ImGui::Text("Am Zug: %s", toString(m_gameMode->getColorOf(m_gameMode->getCurrentPlayer())).data());
    ImGui::Text("Wuerfel: %d", state.getDiceValue());

    ImGui::BeginDisabled(!isMyTurn || state.getPhase() != ludo::TurnPhase::AwaitingRoll);
    if (ImGui::Button("Wuerfeln")) {
        m_gameMode->sendCommand(ludo::RollDiceCommand{m_localPlayer});
    }

    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);
    for (auto& ai : aiControllers) {
        ai.update(deltaTime);
    }

    for (const auto& event : m_gameMode->pollEvents()) {
        std::visit([this]<typename T>(const T& e) {
                if constexpr (std::is_same_v<T, ludo::PieceMovedEvent>) {
                    m_piecePresenter.onPieceMoved(e, m_gameMode->getState());
                }
                if constexpr (std::is_same_v<T, ludo::DiceRolledEvent>) {
                    m_lastEventMessage = std::format("Wuerfel geworfen: {}", e.diceValue);
                }
                // DiceRolledEvent/TurnChangedEvent -> ImGui-State aktualisieren
        }, event);
    }

    m_highlightSystem.update(getMouse(), m_entityRegistry);

    if (auto entity = m_pickingSystem.update(getMouse(), m_entityRegistry)) {
        if (auto pieceIndex = m_piecePresenter.getPieceIndex(*entity)) {
            spdlog::info("Sende MovePieceCommand fuer pieceIndex={}", *pieceIndex);
            m_gameMode->sendCommand(ludo::MovePieceCommand{m_localPlayer, *pieceIndex});
        } else {
            spdlog::warn("Entity {} getroffen, aber keine bekannte Spielfigur (getPieceIndex = nullopt)", entity->value());
        }
    }
}

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

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

    renderHud();
}
