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

#include "Loader.h"

#include "Texture2D.h"
#include "TextureLoader.h"

RawModel Loader::loadToVAO(const std::vector<float> &vertices, const std::vector<float>& normals, const std::vector<float> &textureCoords, const std::vector<int> &indices) {
    GLuint vaoID = createVAO();
    storeDataInAttributeList(0, 3, vertices);
    storeDataInAttributeList(1, 2, textureCoords);
    storeDataInAttributeList(2, 3, normals);
    bindIndicesBuffer(indices);
    unbindVAO();
    return {vaoID, static_cast<int>(indices.size())};
}

Loader::~Loader() {
    cleanUp();
}

void Loader::cleanUp() {
    for (GLuint vaoID: vaoIDs) {
        glDeleteVertexArrays(1, &vaoID);
    }

    for (GLuint vboID: vboIDs) {
        glDeleteBuffers(1, &vboID);
    }

    for (GLuint textureID: textureIDs) {
        glDeleteTextures(1, &textureID);
    }
}

ModelTexture Loader::loadTextureFromFile(const std::string &path) {
    return ModelTexture(loadTexture(path));
}

GLuint Loader::loadTexture(const std::string &path) {
    Texture2D texture = TextureLoader::loadTexture(path);
    textureIDs.push_back(texture.id);
    return texture.id;
}

GLuint Loader::createVAO() {
    GLuint vaoID;
    glGenVertexArrays(1, &vaoID);
    vaoIDs.push_back(vaoID);
    glBindVertexArray(vaoID);
    return vaoID;
}

void Loader::storeDataInAttributeList(int attributeNumber, const int coordinateSize, const std::vector<float> &data) {
    GLuint vboID;
    glGenBuffers(1, &vboID);
    vboIDs.push_back(vboID);

    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), data.data(), GL_STATIC_DRAW);
    glVertexAttribPointer(attributeNumber, coordinateSize, GL_FLOAT, GL_FALSE, 0, nullptr);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Loader::bindIndicesBuffer(const std::vector<int>& indices) {
    GLuint vboID;
    glGenBuffers(1, &vboID);
    vboIDs.push_back(vboID);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(int), indices.data(), GL_STATIC_DRAW);

}

void Loader::unbindVAO() {
    glBindVertexArray(0);
}
