/**
* WebGL Model Viewer - Model.js
* Copyright © Cyril Diagne 2010.
*
* @author kikko.fr
*/

Model = function () {
	
	this.mvMatrix = mat4.create();
	mat4.identity(this.mvMatrix);
	mat4.translate(this.mvMatrix, [0.0, -0.6, -2.5]);
	
	this.meshes = [];
	this.materialList = [];
	
	this.events = new EventDispatcher();
	
	this.wireframeMaterial = new ColorMaterial();
};

Model.prototype = {
	
	
	init : function() {
		
		log("Model : Model Initialization...");
		setTimeout(delegate(this, this.initMeshes), 1);
	},
	
	
	initMeshes : function() {
		
		var currTime = new Date().getTime();
		
		var meshes = this.meshes;
		for(var i=0; i<meshes.length; i++) {
			
			var mesh = meshes[i];
			mesh.mvMatrix = this.mvMatrix;
			mesh.materialList = this.materialList;
			mesh.computeTN(); 	// we want tangents and normals
			mesh.createBuffers();
			this.createTNLines(mesh); // extra debug infos
		}
		log("Model : Initialization Done : ", ((new Date().getTime()-currTime)*0.001).toFixed(3)+"s");
		
		this.initMaterials();
		
		this.events.dispatchEvent("modelReady");
	},
	
	
	initMaterials : function() {
	
		var oneMesh = this.meshes[0];
		for(var i=0; i<this.materialList.length; i++) {
			this.materialList[i].init(oneMesh.hasUV, oneMesh.hasNormals, oneMesh.hasTangents);
		}
	},
	
	
	createTNLines : function(mesh) {
	
		// create lines and wireframe material for rendering
		var v, nPos = vec3.create(), tPos = vec3.create();
		mesh.normalLineBuffer = gl.createBuffer();
		mesh.tangentLineBuffer = gl.createBuffer();
		var bufferData=[], tangentData=[];
		
		for( i = 0; i < mesh.vertices.length; i++ ) {
		
			v = mesh.vertices[i];
			
			vec3.add(v.p, vec3.scale(v.n, 0.03), nPos); //v.p.add(v.n.x(0.025));
			bufferData = bufferData.concat([ v.p[0], v.p[1], v.p[2], nPos[0], nPos[1], nPos[2] ]);
			
			vec3.add(v.p, vec3.scale(v.t, 0.03), tPos);//v.p.add(v.t.x(0.025));
			tangentData = tangentData.concat( v.p[0], v.p[1], v.p[2], tPos[0], tPos[1], tPos[2] );			
		}
		
		gl.bindBuffer(gl.ARRAY_BUFFER, mesh.normalLineBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(bufferData), gl.STATIC_DRAW);
		
		gl.bindBuffer(gl.ARRAY_BUFFER, mesh.tangentLineBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(tangentData), gl.STATIC_DRAW);
	},
	
	
	draw : function() {
		
		if(animate) mat4.rotate(this.mvMatrix, 0.015, [0.0, 1.0, 0.0]);
		
		var mesh;
		for (i = 0; i < this.meshes.length; i++) {	
			
			mesh = this.meshes[i];
			mesh.draw();
			
			if(showNormals) this.drawMeshNormals(mesh);
		}
	},
	
	
	drawMeshNormals : function(mesh) {

		this.wireframeMaterial.enable();
		
		gl.uniformMatrix4fv(this.wireframeMaterial.program.pMatrixUniform, false, projectionMatrix);
		gl.uniformMatrix4fv(this.wireframeMaterial.program.mvMatrixUniform, false, this.mvMatrix);
		
		this.wireframeMaterial.setColor(1.0, 0.0, 0.0, 1.0);
		gl.bindBuffer(gl.ARRAY_BUFFER, mesh.normalLineBuffer);
		gl.vertexAttribPointer(this.wireframeMaterial.program.vertexPosAttrib, 3, gl.FLOAT, false, 3*4, 0);
		gl.drawArrays(gl.LINES, 0, mesh.vertices.length*2);
		
		this.wireframeMaterial.setColor(0.0, 1.0, 0.0, 1.0);
		gl.bindBuffer(gl.ARRAY_BUFFER, mesh.tangentLineBuffer);
		gl.vertexAttribPointer(this.wireframeMaterial.program.vertexPosAttrib, 3, gl.FLOAT, false, 3*4, 0);
		gl.drawArrays(gl.LINES, 0, mesh.vertices.length*2);
		
		this.wireframeMaterial.disable();
	}
}
