#include "cMS3DFileLoader.h"

void cMS3DFileLoader::load(const string& filename)
{
    ifstream file(filename.c_str());
    if(!file)
    {
        cout << "Error, could not open file!" << endl;
        return;
    }
    
    bool error = false;
    char szLine[256];
    char szName[256]; // no names longer than 256 chars
    int nFlags, nIndex;
    
    // skip header and frames infomation
    for(int i = 0; i < 5; ++i) 
        if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
    
    // look at each line
    while(file.good() && !error)
    {
        if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
        
        // get the number of meshes
        int nNumMeshes = 0;
        if (sscanf (szLine, "Meshes: %d", &nNumMeshes) != 1)
            { error = true; break; }
        
        model_.numMeshes_ = nNumMeshes;
        model_.meshes_ = new MS3DMesh[nNumMeshes];
        
        // get each mesh
        for (int i = 0; i < model_.numMeshes_ && !error; i++)
        {
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
            
            // get a mesh: name, flags, material index
            // we only care about the material index
            if (sscanf (szLine, "\"%[^\"]\" %d %d", &szName, &nFlags, &nIndex) != 3)
                { error = true; break; }
            
            model_.meshes_[i].materialIndex_ = nIndex;

            // get each vertex
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

            int nNumVertices = 0;
            if (sscanf (szLine, "%d", &nNumVertices) != 1)
                { error = true; break; }
            
            model_.meshes_[i].numVertices_ = nNumVertices;
            model_.meshes_[i].vertices_ = new MS3DVertex[nNumVertices];
            
            for (int j = 0; j < nNumVertices; j++)
            {
                if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

                if (sscanf (szLine, "%d %f %f %f %f %f %d",
                    &nFlags,
                    &model_.meshes_[i].vertices_[j].x_, 
                    &model_.meshes_[i].vertices_[j].y_, 
                    &model_.meshes_[i].vertices_[j].z_,
                    &model_.meshes_[i].vertices_[j].u_, 
                    &model_.meshes_[i].vertices_[j].v_,
                    &nIndex
                    ) != 7) { error = true; break; }
                
                model_.meshes_[i].vertices_[j].index_ = j;
        
            }

            // skip past vertex normals
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

            int nNumNormals = 0;
            if (sscanf (szLine, "%d", &nNumNormals) != 1)
                { error = true; break; }

            for (int j = 0; j < nNumNormals; j++)
            {
                if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
            }

            // triangles
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

            int nNumTriangles = 0;
            if (sscanf (szLine, "%d", &nNumTriangles) != 1)
                { error = true; break; }
            
            model_.meshes_[i].numTriangles_ = nNumTriangles;
            model_.meshes_[i].triangles_ = new MS3DTriangle[nNumTriangles];
            
            for (int j = 0; j < nNumTriangles; j++)
            {
                if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

                int nNormalIndices[3]; // we dont care about these
                if (sscanf (szLine, "%d %d %d %d %d %d %d %d",
                    &nFlags,
                    &model_.meshes_[i].triangles_[j].v0_, 
                    &model_.meshes_[i].triangles_[j].v1_, 
                    &model_.meshes_[i].triangles_[j].v2_,
                    &nNormalIndices[0], &nNormalIndices[1], &nNormalIndices[2],
                    &nIndex
                    ) != 8) { error = true; break; }
                    
                
            } // end for each triangle
            
        } // end for each mesh
        
        // get materials
        if(file.good()) { file.getline(szLine,256); } else { error = true; break; } // skip a line
        if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
        int nNumMaterials = 0;
        if (sscanf (szLine, "Materials: %d", &nNumMaterials) != 1)
            { error = true; break; }
        
        model_.numMaterials_ = nNumMaterials;
        model_.materials_ = new MS3DMaterial[nNumMaterials];
        
        for (int i = 0; i < nNumMaterials && !error; i++)
        {
            model_.materials_[i].index_ = i;
            // skip name
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
            
            // skip ambient
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

            // skip diffuse
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
            
            // skip specular
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

            // skip emissive
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
            
            // skip shininess
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

            // skip transparency
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }

            // get diffuse texture
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
            
            if (sscanf (szLine, "\"%[^\"]\"", szName) != 1)
                { error = true; break; }
            
            strcpy(model_.materials_[i].textureFilename_, szName);

            // skip alpha texture
            if(file.good()) { file.getline(szLine,256); } else { error = true; break; }
            
        } // end for each material
            
    } // end while can get more lines
}

void cMS3DFileLoader::buildStaticTriangleMesh(cStaticTriangleMesh& mesh)
{
    // add textures
    for(int i = 0; i < model_.numMaterials_; ++i)
    {
        //mesh.addTexture(model_.materials_[i].textureFilename_);
        
        if(i == 2 || i == 4)
            mesh.addTexture(model_.materials_[i].textureFilename_, true);
        else
            mesh.addTexture(model_.materials_[i].textureFilename_, false);
    }
    
    // the vertex indices in each ms3d mesh will restart at 0,
    // but cStaticTriangleMesh will not, so we need to pass 
    // a global index, which is the stored index plus the 
    // the number of vertice we already added in other meshes.
    int verticesInPreviousMeshes = 0; 
    
    // add each mesh
    for(int i = 0; i < model_.numMeshes_; ++i)
    {
        
        // add vertices
        for(int j = 0; j < model_.meshes_[i].numVertices_; ++j)
        {
            mesh.addVertex(	model_.meshes_[i].vertices_[j].x_,
                                model_.meshes_[i].vertices_[j].y_,
                                model_.meshes_[i].vertices_[j].z_,
                                model_.meshes_[i].vertices_[j].u_,
                                1 - model_.meshes_[i].vertices_[j].v_ );
        }
        
        // add triangles
        for(int j = 0; j < model_.meshes_[i].numTriangles_; ++j)
        {
            mesh.addTriangle(	model_.meshes_[i].triangles_[j].v0_ + verticesInPreviousMeshes,
                                model_.meshes_[i].triangles_[j].v1_ + verticesInPreviousMeshes,
                                model_.meshes_[i].triangles_[j].v2_ + verticesInPreviousMeshes,
                                model_.meshes_[i].materialIndex_);
        }
        
        verticesInPreviousMeshes += model_.meshes_[i].numVertices_;
    }
}