#include "OBJModelPrimitive.h"
#include <iostream>

OBJModelPrimitive::OBJModelPrimitive(const std::string& objPath, const std::string& texturePath) 
    : textureID_(0), hasTexture_(false) {
    
    // Load OBJ file
    OBJLoader loader;
    if (!loader.LoadOBJ(objPath)) {
        std::cerr << "Failed to load OBJ file: " << objPath << std::endl;
        return;
    }
    
    // Load texture if provided
    if (!texturePath.empty()) {
        if (texturePath.ends_with(".bmp")) {
            textureID_ = SimpleTextureLoader::LoadBMP(texturePath);
        } else if (texturePath.ends_with(".tga")) {
            textureID_ = SimpleTextureLoader::LoadTGA(texturePath);
        }
        hasTexture_ = (textureID_ != 0);
    }
    
    // Create VAO/VBO/EBO
    glGenVertexArrays(1, &vao_);
    glGenBuffers(1, &vbo_);
    glGenBuffers(1, &ebo_);
    
    glBindVertexArray(vao_);
    
    // Upload vertex data (position + color + normal + texcoord = 11 floats)
    glBindBuffer(GL_ARRAY_BUFFER, vbo_);
    glBufferData(GL_ARRAY_BUFFER, loader.vertices.size() * sizeof(OBJVertex), 
                 loader.vertices.data(), GL_STATIC_DRAW);
    
    // Upload indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, loader.indices.size() * sizeof(unsigned int), 
                 loader.indices.data(), GL_STATIC_DRAW);
    
    // Position attribute (location 0)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(OBJVertex), (void*)offsetof(OBJVertex, position));
    glEnableVertexAttribArray(0);
    
    // Color attribute (location 1)
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(OBJVertex), (void*)offsetof(OBJVertex, color));
    glEnableVertexAttribArray(1);
    
    // Normal attribute (location 2)
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(OBJVertex), (void*)offsetof(OBJVertex, normal));
    glEnableVertexAttribArray(2);
    
    // Texture coordinate attribute (location 3)
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(OBJVertex), (void*)offsetof(OBJVertex, texCoord));
    glEnableVertexAttribArray(3);
    
    glBindVertexArray(0);
    index_count_ = static_cast<GLsizei>(loader.indices.size());
}

OBJModelPrimitive::~OBJModelPrimitive() {
    Cleanup();
}

void OBJModelPrimitive::Render() {
    if (hasTexture_) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, textureID_);
    }
    
    glBindVertexArray(vao_);
    glDrawElements(GL_TRIANGLES, index_count_, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
    
    if (hasTexture_) {
        glBindTexture(GL_TEXTURE_2D, 0);
    }
}

void OBJModelPrimitive::Bind() {
    glBindVertexArray(vao_);
}

void OBJModelPrimitive::Cleanup() {
    if (vao_) glDeleteVertexArrays(1, &vao_);
    if (vbo_) glDeleteBuffers(1, &vbo_);
    if (ebo_) glDeleteBuffers(1, &ebo_);
    if (textureID_) glDeleteTextures(1, &textureID_);
}
