//
//    File: shallo_mesh.cpp
//
//    (C) 2008, Michael Zimmermann
//
///    Licensed under the terms of the Lesser General Public License.
//
#include "shallo_mesh.h"

int ShalloMesh::read ( FILE *f, int ( *updateProgress ) ( int pos ),
                       void ( *setTotal ) ( int size ) ) {
	list<Triangle*> *shapeTriangles;
	list<Vertex*> *shapeVertices;
	vector<Vertex*> vertexIndex;

	int vertexCount = 0;
	int polygonCount = 0;

	fseek ( f, 0, SEEK_END );
	( *setTotal ) ( ftell ( f ) );
	fseek ( f, 0, SEEK_SET );

	shapeTriangles = new list<Triangle*>;
	shapeVertices = new list<Vertex*>;

	// read number of points
	if ( fscanf ( f, "%d", &vertexCount ) != 1 ) {
		FILE_ERROR ( f, "Shallo file format error: vertex/point count" );
		return 3;
	}

	// read vertexes
	for ( int i = 1; i <= vertexCount; i++ ) {
		int id;
		float x, y, z;
		if ( ( fscanf ( f, "%f %f %f %d", &x, &y, &z, &id ) != 4 ) ) {
			FILE_ERROR ( f, "Shallo file format error: vertex value" );
			return 3;
		}
		Vertex *v = new Vertex ( x, y, z );
        v->number = id;
		addVertex ( v );
		vertexIndex.push_back ( v );

		if ( ( *updateProgress ) ( ftell ( f ) ) )
			return 90;

	}

	// read number of triangles
	if ( fscanf ( f, "%d", &polygonCount ) != 1 ) {
		FILE_ERROR ( f, "Shallo file format error: polygon count" );
		return 3;
	}

	// read and process polygons;
    // decrease by "-1" as shallo uses 1..n numbering; mview 0..n-1
	for ( int i = 1; i <= polygonCount; i++ ) { /* Reads the triangles */
		int corners;
		int p1, p2, p3, p4, id;

		fscanf ( f, "%d", &corners );
		if ( corners == 4 ) {
			fscanf ( f, "%d %d %d %d %d\n", &p1, &p2, &p3, &p4, &id );
			p1--;
			p2--;
			p3--;
			p4--;
            if ( ( p1 >= vertexCount ) || ( p2 >= vertexCount ) || ( p3 >= vertexCount ) || ( p4 >= vertexCount ) ) {
				FILE_ERROR ( f, "Shallo file format error: vertex index out of range" );
				return 8;
			}
			Triangle *tri = new Triangle ( vertexIndex[p1], vertexIndex[p2], vertexIndex[p3] );
			addTriangle ( tri );
			shapeTriangles->push_back ( tri );

			tri = new Triangle ( vertexIndex[p3], vertexIndex[p4], vertexIndex[p1] );
			addTriangle ( tri );
			shapeTriangles->push_back ( tri );
		} else {
			fscanf ( f, "%d %d %d %d\n", &p1, &p2, &p3, &id );
			p1--;
			p2--;
			p3--;
            if ( ( p1 >= vertexCount ) || ( p2 >= vertexCount ) || ( p3 >= vertexCount ) ) {
				FILE_ERROR ( f, "Shallo file format error: vertex index out of range" );
				return 8;
			}
			Triangle *tri = new Triangle ( vertexIndex[p1], vertexIndex[p2], vertexIndex[p3] );
			addTriangle ( tri );
			shapeTriangles->push_back ( tri );
		}

		if ( ( *updateProgress ) ( ftell ( f ) ) )
			return 90;
	}

	// copy the vertices of this shape over
	shapeVertices->insert ( shapeVertices->begin(), vertexIndex.begin(), vertexIndex.end() );
	shapes->push_back ( new Shape ( shapeTriangles, shapeVertices ) );

	return 0;
}

void ShalloMesh::write ( FILE *f, const char *comment ) {
	int n;
	list<Triangle*>::iterator it;
	list<Vertex*>::iterator iv;
	Vertex v;

	// read routine does not support comments yet
	// fprintf(f, "#ShalloMesh\n");
	// fprintf(f, "# %s\n", comment);

	// size of vertices
	fprintf ( f, "%d\n", vertices->size() );

	n = 1;  // vertices
	for ( iv = vertices->begin(); iv != vertices->end(); iv++ ) {
		calcOriginalCoordinates ( *iv, &v );
        fprintf ( f, "%f %f %f %d\n", v.x(), v.y(), v.z(), n );
        ( *iv )->number = n;
        n++;
    }

    
	// size of triangles
	fprintf ( f, "%d\n", triangles->size() );

	// triangles
	n = 0;
	for ( it = triangles->begin(); it != triangles->end(); it++ ) {
		n++;
		fprintf ( f, "3 %d %d %d %d\n", ( *it )->vertices[0]->number,
		          ( *it )->vertices[1]->number, ( *it )->vertices[2]->number, n );
	}
}
