#ifndef MESH_H
#define MESH_H

typedef struct {
    V3F pos;
    V3F normal;
    V2F tex_coords;
} Vertex;

typedef struct {
    U32 vao;
    Vertex *vertices;
    U32 vertex_count;
    U32 *indices;
    U32 index_count;
} Mesh;

Vertex
vertex(V3F pos, V3F normal, V2F tex_coords)
{
    Vertex result;
    result.pos = pos;
    result.normal = normal;
    result.tex_coords = tex_coords;
    return(result);
}

Mesh *
mesh_init(Arena *arena,
          Vertex *vertices, U32 vertex_count,
          U32 *indices, U32 index_count)
{
    Mesh *mesh = 0;
    U32 vbo, ebo;
    
    if (!vertices)
    {
        printf("[ERROR]: Vertices is null\n");
        return(mesh);
    }
    if (!indices)
    {
        printf("[ERROR]: Indices is null\n");
        return(mesh);
    }
    
    Assert(arena);
    mesh = arena_push_size(arena, sizeof(Mesh));
    
    mesh->vertices = vertices;
    mesh->vertex_count = vertex_count;
    
    mesh->indices = indices;
    mesh->index_count = index_count;
    
    glGenVertexArrays(1, &mesh->vao);
    glBindVertexArray(mesh->vao);
    
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, vertex_count*sizeof(Vertex), vertices, GL_STATIC_DRAW);
    
    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_count*sizeof(U32), indices, GL_STATIC_DRAW);
    
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                          (void *)(OffsetOfMember(Vertex, pos)));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                          (void *)(OffsetOfMember(Vertex, normal)));
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                          (void *)(OffsetOfMember(Vertex, tex_coords)));
    
    glBindVertexArray(0);
    
    return(mesh);
}

void
mesh_draw(Mesh *mesh)
{
    if (!mesh)
        return;
    
    glBindVertexArray(mesh->vao);
    glDrawElements(GL_TRIANGLES, mesh->index_count, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

#endif /* MESH_H */