#include "engine/obj_loader.hpp"
#include <fstream>
#include <sstream>

OBJLoader::OBJLoader(std::string filepath) : filepath(filepath), loaded(true) {
    std::ifstream file(filepath);
    if (!file.is_open()) {
        loaded = false;
        return;
    }

    std::vector<glm::vec3> temp_positions;
    std::vector<glm::vec3> temp_normals;
    std::vector<glm::vec2> temp_texCoords;

    std::string line;
    while (std::getline(file, line)) {
        std::istringstream ss(line);
        std::string prefix;
        ss >> prefix;

        if (prefix == "v") {
            glm::vec3 position;
            ss >> position.x >> position.y >> position.z;
            temp_positions.push_back(position);
        } else if (prefix == "vn") {
            glm::vec3 normal;
            ss >> normal.x >> normal.y >> normal.z;
            temp_normals.push_back(normal);
        } else if (prefix == "vt") {
            glm::vec2 texCoord;
            ss >> texCoord.x >> texCoord.y;
            temp_texCoords.push_back(texCoord);
        } else if (prefix == "f") {
            unsigned int posIdx[3], texIdx[3], normIdx[3];
            char slash; // to consume the '/' characters

            for (int i = 0; i < 3; ++i) {
                ss >> posIdx[i] >> slash >> texIdx[i] >> slash >> normIdx[i];
                Vertex vertex;
                vertex.position = temp_positions[posIdx[i] - 1];
                vertex.texCoord = temp_texCoords[texIdx[i] - 1];
                vertex.normal = temp_normals[normIdx[i] - 1];
                vertices.push_back(vertex);
                indices.push_back(static_cast<unsigned int>(vertices.size() - 1));
            }
        }
    }
}

// Convert loaded vertex data to a contiguous float array
float* OBJLoader::getVertexData() {
    size_t vertexCount = vertices.size();
    float* vertexData = new float[vertexCount * 8]; // 3 pos + 3 normal + 2 texCoord
    for (size_t i = 0; i < vertexCount; ++i) {
        vertexData[i * 8 + 0] = vertices[i].position.x;
        vertexData[i * 8 + 1] = vertices[i].position.y;
        vertexData[i * 8 + 2] = vertices[i].position.z;
        vertexData[i * 8 + 3] = vertices[i].normal.x;
        vertexData[i * 8 + 4] = vertices[i].normal.y;
        vertexData[i * 8 + 5] = vertices[i].normal.z;
        vertexData[i * 8 + 6] = vertices[i].texCoord.x;
        vertexData[i * 8 + 7] = vertices[i].texCoord.y;
    }
    return vertexData;
}

// Convert loaded index data to a contiguous unsigned int array
unsigned int* OBJLoader::getIndexData() {
    size_t indexCount = indices.size();
    unsigned int* indexData = new unsigned int[indexCount];
    for (size_t i = 0; i < indexCount; ++i) {
        indexData[i] = indices[i];
    }
    return indexData;
}

size_t OBJLoader::getVertexCount() {
    return vertices.size();
}

size_t OBJLoader::getIndexCount() {
    return indices.size();
}