//
// Created by sebastian on 24.12.25.
//

#include "Renderer.h"

#include <ranges>

#include "../../game/hexWorld/HexTile.h"
#include "../core/Application.h"
#include "../layer/entities/Light.h"
#include "../toolbox/MathUtils.h"
#include "glad/glad.h"
#include "glm/ext/matrix_clip_space.hpp"
#include "model/TexturedModel.h"



void Renderer::prepare(const Camera& camera, const Light& light) {
    const glm::mat4 viewMatrix = MathUtils::createViewMatrix(camera);
    staticShader.start();
    staticShader.loadLight(light.getPosition(), light.getColor());
    staticShader.loadViewMatrix(viewMatrix);
}


void Renderer::renderEntities(const std::unordered_map<TexturedModel *, std::vector<Entity *>>& entities) {
    for (const auto& [texturedModel, batch] : entities) {
        prepareTexturedModel(*texturedModel);
        for (const auto& entity : batch) {
            prepareInstance(*entity);
            glDrawElements(GL_TRIANGLES, texturedModel->getRawModel()->vertexCount, GL_UNSIGNED_INT, 0);
        }

        unbindTexturedModel();
    }
}

void Renderer::prepareTexturedModel(const TexturedModel &texturedModel) {
    auto rawModel = texturedModel.getRawModel();
    glBindVertexArray(rawModel->vaoID);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texturedModel.getTexture()->getTextureID());
}

void Renderer::unbindTexturedModel() {
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glBindVertexArray(0);
}

void Renderer::prepareInstance(const Entity &entity) {
    glm::mat4 transformationMatrix = MathUtils::createTransformationMatrix(entity.getPosition(), entity.getRotX(), entity.getRotY(), entity.getRotZ(), entity.getScale());
    staticShader.loadTransformationMatrix(transformationMatrix);
}

void Renderer::finalizeFrame() {
    staticShader.stop();
}



