#include <iostream>

#include "Mesh.h"

Mesh::Mesh() : m_VAO(0), m_VBO(0), m_EBO(0), m_indexCount(0) {}

Mesh::~Mesh() {
    glDeleteVertexArrays(1, &m_VAO);
    glDeleteBuffers(1, &m_VBO);
    glDeleteBuffers(1, &m_EBO);
}

void Mesh::init() {
    // Generate all the OpenGL objects
    glGenVertexArrays(1, &m_VAO);
    glGenBuffers(1, &m_VBO);
    glGenBuffers(1, &m_EBO);

    // Bind the VAO and set up the vertex attributes
    glBindVertexArray(m_VAO);

    // 1. Bind VBO
    glBindBuffer(GL_ARRAY_BUFFER, m_VBO);

    // 2. Set up attributes (this layout is now saved in the VAO)
    // Position Attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // Normal Attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    // VoxelKind Attribute
    glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    // 3. Bind EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);

    // 4. Unbind VAO (good practice)
    glBindVertexArray(0);
}

void Mesh::uploadData(const std::vector<float> &vboData, const std::vector<unsigned int> &eboData) {
    m_indexCount = eboData.size();

    // std::cout << "Uploading mesh: " << vboData.size() << " floats, " << eboData.size() << " indices" << std::endl;

    // Bind VAO first, then upload buffer data
    glBindVertexArray(m_VAO);

    glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
    glBufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(float), vboData.data(), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, eboData.size() * sizeof(unsigned int), eboData.data(), GL_STATIC_DRAW);
    glBindVertexArray(0);
}

void Mesh::draw() {
    if (m_indexCount == 0) return;

    glBindVertexArray(m_VAO);
    glDrawElements(GL_TRIANGLES, m_indexCount, GL_UNSIGNED_INT, nullptr);
    glBindVertexArray(0);
}
