/*
 * Copyright © 2008 Ben Smith
 * Copyright © 2010-2011 Linaro Limited
 *
 * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
 *
 * glmark2 is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * glmark2.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *  Ben Smith (original glmark benchmark)
 *  Alexandros Frantzis (glmark2)
 */
#include "mesh.h"
#include "model.h"
#include "vec.h"
#include "log.h"
#include "options.h"
#include "util.h"
#include "float.h"
#include "math.h"
#include <fstream>
#include <sstream>
#include <memory>

using std::string;
using std::vector;
using LibMatrix::vec3;
using LibMatrix::uvec3;

#define read_or_fail(file, dst, size) do { \
    file.read(reinterpret_cast<char *>((dst)), (size)); \
    if (file.gcount() < (std::streamsize)(size)) { \
        Log::error("%s: %d: Failed to read %zd bytes from 3ds file (read %zd)\n", \
                   __FUNCTION__, __LINE__, \
                   (size_t)(size), file.gcount()); \
        return false; \
    } \
} while(0);

/**
 * Computes the bounding box for a Model::Object.
 *
 * @param object the Model object
 */
void
Model::compute_bounding_box(const Object& object)
{
    float minX(FLT_MAX);
    float maxX(FLT_MIN);
    float minY(FLT_MAX);
    float maxY(FLT_MIN);
    float minZ(FLT_MAX);
    float maxZ(FLT_MIN);
    for (vector<Vertex>::const_iterator vIt = object.vertices.begin(); vIt != object.vertices.end(); vIt++)
    {
        const vec3& curVtx = vIt->v;
        if (curVtx.x() < minX)
        {
            minX = curVtx.x();
        }
        if (curVtx.x() > maxX)
        {
            maxX = curVtx.x();
        }
        if (curVtx.y() < minY)
        {
            minY = curVtx.y();
        }
        if (curVtx.y() > maxY)
        {
            maxY = curVtx.y();
        }
        if (curVtx.z() < minZ)
        {
            minZ = curVtx.z();
        }
        if (curVtx.z() > maxZ)
        {
            maxZ = curVtx.z();
        }
    }
    maxVec_ = vec3(maxX, maxY, maxZ);
    minVec_ = vec3(minX, minY, minZ);
}

/**
 * Appends the vertices of a Model::Object to a Mesh.
 *
 * @param object the object to append
 * @param mesh the mesh to append to
 * @param p_pos the attribute position to use for the 'position' attribute
 * @param n_pos the attribute position to use for the 'normal' attribute
 * @param t_pos the attribute position to use for the 'texcoord' attribute
 */
void
Model::append_object_to_mesh(const Object &object, Mesh &mesh,
                             int p_pos, int n_pos, int t_pos,
                             int nt_pos, int nb_pos)
{
    size_t face_count = object.faces.size();

    for(size_t i = 0; i < 3 * face_count; i += 3)
    {
        const Face &face = object.faces[i / 3];
        const Vertex &a = object.vertices[face.a];
        const Vertex &b = object.vertices[face.b];
        const Vertex &c = object.vertices[face.c];

        mesh.next_vertex();
        if (p_pos >= 0)
            mesh.set_attrib(p_pos, a.v);
        if (n_pos >= 0)
            mesh.set_attrib(n_pos, a.n);
        if (t_pos >= 0)
            mesh.set_attrib(t_pos, a.t);
        if (nt_pos >= 0)
            mesh.set_attrib(nt_pos, a.nt);
        if (nb_pos >= 0)
            mesh.set_attrib(nb_pos, a.nb);

        mesh.next_vertex();
        if (p_pos >= 0)
            mesh.set_attrib(p_pos, b.v);
        if (n_pos >= 0)
            mesh.set_attrib(n_pos, b.n);
        if (t_pos >= 0)
            mesh.set_attrib(t_pos, b.t);
        if (nt_pos >= 0)
            mesh.set_attrib(nt_pos, b.nt);
        if (nb_pos >= 0)
            mesh.set_attrib(nb_pos, b.nb);

        mesh.next_vertex();
        if (p_pos >= 0)
            mesh.set_attrib(p_pos, c.v);
        if (n_pos >= 0)
            mesh.set_attrib(n_pos, c.n);
        if (t_pos >= 0)
            mesh.set_attrib(t_pos, c.t);
        if (nt_pos >= 0)
            mesh.set_attrib(nt_pos, c.nt);
        if (nb_pos >= 0)
            mesh.set_attrib(nb_pos, c.nb);
    }
}

/**
 * Converts a model to a mesh using the default attributes bindings.
 *
 * The default attributes and their order is: Position, Normal, Texcoord
 *
 * @param mesh the mesh to populate
 */
void
Model::convert_to_mesh(Mesh &mesh)
{
    std::vector<std::pair<AttribType, int> > attribs;

    attribs.push_back(std::pair<AttribType, int>(AttribTypePosition, 3));
    attribs.push_back(std::pair<AttribType, int>(AttribTypeNormal, 3));
    attribs.push_back(std::pair<AttribType, int>(AttribTypeTexcoord, 2));

    convert_to_mesh(mesh, attribs);
}

/**
 * Converts a model to a mesh using custom attribute bindings.
 *
 * The attribute bindings are pairs of <AttribType, dimensionality>.
 *
 * @param mesh the mesh to populate
 * @param attribs the attribute bindings to use
 */
void
Model::convert_to_mesh(Mesh &mesh,
                       const std::vector<std::pair<AttribType, int> > &attribs)
{
    std::vector<int> format;
    int p_pos = -1;
    int n_pos = -1;
    int t_pos = -1;
    int nt_pos = -1;
    int nb_pos = -1;

    mesh.reset();

    for (std::vector<std::pair<AttribType, int> >::const_iterator ai = attribs.begin();
         ai != attribs.end();
         ai++)
    {
        format.push_back(ai->second);
        if (ai->first == AttribTypePosition)
            p_pos = ai - attribs.begin();
        else if (ai->first == AttribTypeNormal)
            n_pos = ai - attribs.begin();
        else if (ai->first == AttribTypeTexcoord)
            t_pos = ai - attribs.begin();
        else if (ai->first == AttribTypeTangent)
            nt_pos = ai - attribs.begin();
        else if (ai->first == AttribTypeBitangent)
            nb_pos = ai - attribs.begin();
    }

    mesh.set_vertex_format(format);

    for (std::vector<Object>::const_iterator iter = objects_.begin();
         iter != objects_.end();
         iter++)
    {
        append_object_to_mesh(*iter, mesh, p_pos, n_pos, t_pos, nt_pos, nb_pos);
    }
}

void
Model::calculate_texcoords()
{
    // Since the model didn't come with texcoords, and we don't actually know
    // if it came with normals, either, we'll use positional spherical mapping
    // to generate texcoords for the model.  See:
    // http://www.mvps.org/directx/articles/spheremap.htm for more details.
    vec3 centerVec = maxVec_ + minVec_;
    centerVec *= 0.5;
    
    for (std::vector<Object>::iterator iter = objects_.begin();
         iter != objects_.end();
         iter++)
    {
        Object &object = *iter;
        for (vector<Vertex>::iterator vertexIt = object.vertices.begin();
             vertexIt != object.vertices.end();
             vertexIt++)
        {
            Vertex& curVertex = *vertexIt;
            vec3 vnorm(curVertex.v - centerVec);
            vnorm.normalize();
            curVertex.t.x(asinf(vnorm.x()) / M_PI + 0.5);
            curVertex.t.y(asinf(vnorm.y()) / M_PI + 0.5);
        }
    }
}

/**
 * Calculates the normal vectors of the model vertices.
 */
void
Model::calculate_normals()
{
    LibMatrix::vec3 n;

    for (std::vector<Object>::iterator iter = objects_.begin();
         iter != objects_.end();
         iter++)
    {
        Object &object = *iter;

        for (vector<Face>::const_iterator f_iter = object.faces.begin();
             f_iter != object.faces.end();
             f_iter++)
        {
            const Face &face = *f_iter;
            Vertex &a = object.vertices[face.a];
            Vertex &b = object.vertices[face.b];
            Vertex &c = object.vertices[face.c];

            /* Calculate normal */
            n = LibMatrix::vec3::cross(b.v - a.v, c.v - a.v);
            n.normalize();
            a.n += n;
            b.n += n;
            c.n += n;

            LibMatrix::vec3 q1(b.v - a.v);
            LibMatrix::vec3 q2(c.v - a.v);
            LibMatrix::vec2 u1(b.t - a.t);
            LibMatrix::vec2 u2(c.t - a.t);
            float det = (u1.x() * u2.y() - u2.x() * u1.y());

            /* Calculate tangent */
            LibMatrix::vec3 nt;
            nt.x(det * (u2.y() * q1.x() - u1.y() * q2.x()));
            nt.y(det * (u2.y() * q1.y() - u1.y() * q2.y()));
            nt.z(det * (u2.y() * q1.z() - u1.y() * q2.z()));
            nt.normalize();
            a.nt += nt;
            b.nt += nt;
            c.nt += nt;

            /* Calculate bitangent */
            LibMatrix::vec3 nb;
            nb.x(det * (u1.x() * q2.x() - u2.x() * q1.x()));
            nb.y(det * (u1.x() * q2.y() - u2.x() * q1.y()));
            nb.z(det * (u1.x() * q2.z() - u2.x() * q1.z()));
            nb.normalize();
            a.nb += nb;
            b.nb += nb;
            c.nb += nb;
        }

        for (vector<Vertex>::iterator v_iter = object.vertices.begin();
             v_iter != object.vertices.end();
             v_iter++)
        {
            Vertex &v = *v_iter;
            /* Orthogonalize */
            v.nt = (v.nt - v.n * LibMatrix::vec3::dot(v.nt, v.n));
            v.n.normalize();
            v.nt.normalize();
            v.nb.normalize();
        }

    }
}

/**
 * Load a model from a 3DS file.
 *
 * @param filename the name of the file
 *
 * @return whether loading succeeded
 */
bool
Model::load_3ds(const std::string &filename)
{
    Object *object(0);

    Log::debug("Loading model from 3ds file '%s'\n", filename.c_str());

    const std::auto_ptr<std::istream> input_file_ptr(Util::get_resource(filename));
    std::istream& input_file(*input_file_ptr);

    if (!input_file) {
        Log::error("Could not open 3ds file '%s'\n", filename.c_str());
        return false;
    }

    // Loop to scan the whole file
    while (!input_file.eof()) {
        uint16_t chunk_id;
        uint32_t chunk_length;

        // Read the chunk header
        input_file.read(reinterpret_cast<char *>(&chunk_id), 2);
        if (input_file.gcount() == 0) {
            continue;
        }
        else if (input_file.gcount() < 2) {
            Log::error("%s: %d: Failed to read %zd bytes from 3ds file (read %zd)\n",
                       __FUNCTION__, __LINE__, 2, input_file.gcount());
            return false;
        }

        //Read the lenght of the chunk
        read_or_fail(input_file, &chunk_length, 4);

        switch (chunk_id)
        {
            //----------------- MAIN3DS -----------------
            // Description: Main chunk, contains all the other chunks
            // Chunk ID: 4d4d
            // Chunk Lenght: 0 + sub chunks
            //-------------------------------------------
            case 0x4d4d:
                break;

            //----------------- EDIT3DS -----------------
            // Description: 3D Editor chunk, objects layout info
            // Chunk ID: 3d3d (hex)
            // Chunk Lenght: 0 + sub chunks
            //-------------------------------------------
            case 0x3d3d:
                break;

            //--------------- EDIT_OBJECT ---------------
            // Description: Object block, info for each object
            // Chunk ID: 4000 (hex)
            // Chunk Lenght: len(object name) + sub chunks
            //-------------------------------------------
            case 0x4000:
                {
                std::stringstream ss;
                unsigned char c = 1;

                for (int i = 0; i < 20 && c != '\0'; i++) {
                    read_or_fail(input_file, &c, 1);
                    ss << c;
                }

                objects_.push_back(Object(ss.str()));
                object = &objects_.back();
                }
                break;

            //--------------- OBJ_TRIMESH ---------------
            // Description: Triangular mesh, contains chunks for 3d mesh info
            // Chunk ID: 4100 (hex)
            // Chunk Lenght: 0 + sub chunks
            //-------------------------------------------
            case 0x4100:
                break;

            //--------------- TRI_VERTEXL ---------------
            // Description: Vertices list
            // Chunk ID: 4110 (hex)
            // Chunk Lenght: 1 x unsigned short (number of vertices)
            //             + 3 x float (vertex coordinates) x (number of vertices)
            //             + sub chunks
            //-------------------------------------------
            case 0x4110:
                {
                uint16_t qty;
                read_or_fail(input_file, &qty, sizeof(uint16_t));
                object->vertices.resize(qty);

                for (uint16_t i = 0; i < qty; i++) {
                    float f[3];
                    read_or_fail(input_file, f, sizeof(float) * 3);
                    object->vertices[i].v.x(f[0]);
                    object->vertices[i].v.y(f[1]);
                    object->vertices[i].v.z(f[2]);
                }
                }
                break;

            //--------------- TRI_FACEL1 ----------------
            // Description: Polygons (faces) list
            // Chunk ID: 4120 (hex)
            // Chunk Lenght: 1 x unsigned short (number of polygons)
            //             + 3 x unsigned short (polygon points) x (number of polygons)
            //             + sub chunks
            //-------------------------------------------
            case 0x4120:
                {
                uint16_t qty;
                read_or_fail(input_file, &qty, sizeof(uint16_t));
                object->faces.resize(qty);
                for (uint16_t i = 0; i < qty; i++) {
                    read_or_fail(input_file, &object->faces[i].a, sizeof(uint16_t));
                    read_or_fail(input_file, &object->faces[i].b, sizeof(uint16_t));
                    read_or_fail(input_file, &object->faces[i].c, sizeof(uint16_t));
                    read_or_fail(input_file, &object->faces[i].face_flags, sizeof(uint16_t));
                }
                }
                break;

            //------------- TRI_MAPPINGCOORS ------------
            // Description: Vertices list
            // Chunk ID: 4140 (hex)
            // Chunk Lenght: 1 x unsigned short (number of mapping points)
            //             + 2 x float (mapping coordinates) x (number of mapping points)
            //             + sub chunks
            //-------------------------------------------
            case 0x4140:
                {
                uint16_t qty;
                read_or_fail(input_file, &qty, sizeof(uint16_t));
                for (uint16_t i = 0; i < qty; i++) {
                    float f[2];
                    read_or_fail(input_file, f, sizeof(float) * 2);
                    object->vertices[i].t.x(f[0]);
                    object->vertices[i].t.y(f[1]);
                }
                }
                gotTexcoords_ = true;
                break;

            //----------- Skip unknow chunks ------------
            //We need to skip all the chunks that currently we don't use
            //We use the chunk lenght information to set the file pointer
            //to the same level next chunk
            //-------------------------------------------
            default:
                input_file.seekg(chunk_length - 6, std::ios::cur);
        }
    }

    // Compute bounding box for perspective projection
    compute_bounding_box(*object);

    if (Options::show_debug) {
        for (std::vector<Object>::const_iterator iter = objects_.begin();
             iter != objects_.end();
             iter++)
        {
            Log::debug("    Object name: %s Vertex count: %d Face count: %d\n",
                       iter->name.c_str(), iter->vertices.size(), iter->faces.size());
        }
    }

    return true;
}

/**
 * Parse vec3 values from an OBJ file.
 *
 * @param source the source line to parse
 * @param v the vec3 to populate
 */
static void
obj_get_values(const string& source, vec3& v)
{
    // Skip the definition type...
    string::size_type endPos = source.find(" ");
    string::size_type startPos(0);
    if (endPos == string::npos)
    {
        Log::error("Bad element '%s'\n", source.c_str());
        return;
    }
    // Find the first value...
    startPos = endPos + 1;
    endPos = source.find(" ", startPos);
    if (endPos == string::npos)
    {
        Log::error("Bad element '%s'\n", source.c_str());
        return;
    }
    string::size_type numChars(endPos - startPos);
    string xs(source, startPos, numChars);
    float x = Util::fromString<float>(xs);
    // Then the second value...
    startPos = endPos + 1;
    endPos = source.find(" ", startPos);
    if (endPos == string::npos)
    {
        Log::error("Bad element '%s'\n", source.c_str());
        return;
    }
    numChars = endPos - startPos;
    string ys(source, startPos, numChars);
    float y = Util::fromString<float>(ys);
    // And the third value (there might be a fourth, but we don't care)...
    startPos = endPos + 1;
    endPos = source.find(" ", startPos);
    if (endPos == string::npos)
    {
        numChars = endPos;
    }
    else
    {
        numChars = endPos - startPos;
    }
    string zs(source, startPos, endPos - startPos);
    float z = Util::fromString<float>(zs);
    v.x(x);
    v.y(y);
    v.z(z);
}

/**
 * Parse uvec3 values from an OBJ file.
 *
 * @param source the source line to parse
 * @param v the uvec3 to populate
 */
static void
obj_get_values(const string& source, uvec3& v)
{
    // Skip the definition type...
    string::size_type endPos = source.find(" ");
    string::size_type startPos(0);
    if (endPos == string::npos)
    {
        Log::error("Bad element '%s'\n", source.c_str());
        return;
    }
    // Find the first value...
    startPos = endPos + 1;
    endPos = source.find(" ", startPos);
    if (endPos == string::npos)
    {
        Log::error("Bad element '%s'\n", source.c_str());
        return;
    }
    string::size_type numChars(endPos - startPos);
    string xs(source, startPos, numChars);
    unsigned int x = Util::fromString<unsigned int>(xs);
    // Then the second value...
    startPos = endPos+1;
    endPos = source.find(" ", startPos);
    if (endPos == string::npos)
    {
        Log::error("Bad element '%s'\n", source.c_str());
        return;
    }
    numChars = endPos - startPos;
    string ys(source, startPos, numChars);
    unsigned int y = Util::fromString<unsigned int>(ys);
    // And the third value (there might be a fourth, but we don't care)...
    startPos = endPos + 1;
    endPos = source.find(" ", startPos);
    if (endPos == string::npos)
    {
        numChars = endPos;
    }
    else
    {
        numChars = endPos - startPos;
    }
    string zs(source, startPos, numChars);
    unsigned int z = Util::fromString<unsigned int>(zs);
    v.x(x);
    v.y(y);
    v.z(z);
}

/**
 * Load a model from an OBJ file.
 *
 * @param filename the name of the file
 *
 * @return whether loading succeeded
 */
bool
Model::load_obj(const std::string &filename)
{
    Log::debug("Loading model from obj file '%s'\n", filename.c_str());

    const std::auto_ptr<std::istream> input_file_ptr(Util::get_resource(filename));
    std::istream& inputFile(*input_file_ptr);
    if (!inputFile)
    {
        Log::error("Failed to open '%s'\n", filename.c_str());
        return false;
    }

    vector<string> sourceVec;
    string curLine;
    while (getline(inputFile, curLine))
    {
        sourceVec.push_back(curLine);
    }

    // Give ourselves an object to populate.
    objects_.push_back(Object(filename));
    Object& object(objects_.back());

    static const string vertex_definition("v");
    static const string normal_definition("vn");
    static const string texcoord_definition("vt");
    static const string face_definition("f");
    for (vector<string>::const_iterator lineIt = sourceVec.begin();
         lineIt != sourceVec.end();
         lineIt++)
    {
        const string& curSrc = *lineIt;
        // Is it a vertex attribute, a face description, comment or other?
        // We only care about the first two, we ignore comments, object names,
        // group names, smoothing groups, etc.
        string::size_type startPos(0);
        string::size_type spacePos = curSrc.find(" ", startPos);
        string definitionType(curSrc, startPos, spacePos - startPos);
        if (definitionType == vertex_definition)
        {
            Vertex v;
            obj_get_values(curSrc, v.v);
            object.vertices.push_back(v);
        }
        else if (definitionType == normal_definition)
        {
            // If we encounter an OBJ model with normals, we can update this
            // to update object.vertices.n directly
            Log::debug("We got a normal...\n");
        }
        else if (definitionType == texcoord_definition)
        {
            // If we encounter an OBJ model with normals, we can update this
            // to update object.vertices.t directly
            Log::debug("We got a texcoord...\n");
        }
        else if (definitionType == face_definition)
        {
            uvec3 v;
            obj_get_values(curSrc, v);
            Face f;
            // OBJ models index from '1'.
            f.a = v.x() - 1;
            f.b = v.y() - 1;
            f.c = v.z() - 1;
            object.faces.push_back(f);
        }
    }
    // Compute bounding box for perspective projection
    compute_bounding_box(object);

    Log::debug("Object populated with %u vertices and %u faces.\n",
        object.vertices.size(), object.faces.size());
    return true;
}

namespace ModelPrivate
{
ModelMap modelMap;
}

/**
 * Locate all available models.
 *
 * This method scans the built-in data paths and build a database of usable
 * models available to scenes.  Map is available on a read-only basis to scenes
 * that might find it useful for listing models, etc.
 *
 * @return a map containing information about the located models
 */
const ModelMap&
Model::find_models()
{
    if (!ModelPrivate::modelMap.empty())
    {
        return ModelPrivate::modelMap;
    }
    vector<string> pathVec;
    string dataDir(GLMARK_DATA_PATH"/models");
    Util::list_files(dataDir, pathVec);
#ifdef GLMARK_EXTRAS_PATH
    string extrasDir(GLMARK_EXTRAS_PATH"/models");
    Util::list_files(extrasDir, pathVec);
#endif

    // Now that we have a list of all of the model files available to us,
    // let's go through and pull out the names and what format they're in
    // so the scene can decide which ones to use.
    for(vector<string>::const_iterator pathIt = pathVec.begin();
        pathIt != pathVec.end();
        pathIt++)
    {
        const string& curPath = *pathIt;
        string::size_type namePos(0);
        string::size_type slashPos = curPath.rfind("/");
        if (slashPos != string::npos)
        {
            // Advance to the first character after the last slash
            namePos = slashPos + 1;
        }

        ModelFormat format(MODEL_INVALID);
        string::size_type extPos = curPath.rfind(".3ds");
        if (extPos == string::npos)
        {
            // It's not a 3ds model
            extPos = curPath.rfind(".obj");
            if (extPos == string::npos)
            {
                // It's not an obj model either, so skip it.
                continue;
            }
            format = MODEL_OBJ;
        }
        else
        {
            // It's a 3ds model
            format = MODEL_3DS;
        }

        string name(curPath, namePos, extPos - namePos);
        ModelDescriptor* desc = new ModelDescriptor(name, format, curPath);
        ModelPrivate::modelMap.insert(std::make_pair(name, desc));
    }

    return ModelPrivate::modelMap;
}

/**
 * Load a model by name.
 *
 * You must initialize the available model collection using
 * Model::find_models() before using this method.
 *
 * @param modelName the model name
 *
 * @return whether the operation succeeded
 */
bool
Model::load(const string& modelName)
{
    bool retVal(false);
    ModelMap::const_iterator modelIt = ModelPrivate::modelMap.find(modelName);
    if (modelIt == ModelPrivate::modelMap.end())
    {
        return retVal;
    }

    ModelDescriptor* desc = modelIt->second;
    switch (desc->format())
    {
        case MODEL_INVALID:
            break;
        case MODEL_3DS:
            retVal = load_3ds(desc->pathname());
            break;
        case MODEL_OBJ:
            retVal = load_obj(desc->pathname());
            break;
    }

    return retVal;
}
