// http://threejs.org/examples/webgl_interactive_cubes_gpu.html

var pos = new THREE.Vector3();
var normal = new THREE.Vector3();

var FXBirdLathe = function () {

	FRAME.Module.call( this );

	this.parameters.input = {
		phase: 0
	};

	var phase;
	var width = renderer.domElement.width;
	var height = renderer.domElement.height;

	var camera = new THREE.PerspectiveCamera( 60, width / height, 0.0001, 100 );

	var scene = new THREE.Scene;

  	var ambientLight = new THREE.AmbientLight( 0xFF666666 );
    scene.add(ambientLight);

	var light1 = new THREE.PointLight( 0xffffff, 5, 300 );
	
	light1.position.set ( -20, 30, 250 );
	scene.add( light1 );

	this.numCubes = 50;
	//this.cubeSize = 200;

	this.cubeGeometry = new THREE.CubeGeometry(1,1,1);

	this.cubeMaterial = new THREE.ShaderMaterial( 
	{
		uniforms: 
		{
			texture:   { type: "t", value: resourceManager.getTexture("particle_steam") },
		},
		attributes:
		{
			customVisible:	{ type: 'f',  value: [] },
			customSize:		{ type: 'f',  value: [] },
			customColor:	{ type: 'c',  value: new THREE.Color( 0xffffff ) },
			customOpacity:	{ type: 'f',  value: [] }
		},
		vertexShader: [

			"attribute float customSize;",
			"void main()",
			"{",
				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
				"gl_PointSize = customSize * ( 300.0 / length( mvPosition.xyz ) );",     // scale particles as objects in 3D space
				"gl_Position = projectionMatrix * mvPosition;",
			"}"
			].join("\n"),

		fragmentShader: [

			"uniform sampler2D texture;",
			"uniform float opacity;",
			"void main()", 
			"{",
				"gl_FragColor = texture2D( texture,  gl_PointCoord );",    
			"}"
			].join("\n"),

		transparent: true, 
		blending: THREE.NormalBlending, 
		depthTest: true,
		depthWrite: false
	});

    this.cubeMaterial = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        wireframe: false
    });

	this.cubeMaterial = new THREE.MeshLambertMaterial({ 
		color: 0xffffff, 
		shading: THREE.FlatShading,
//		vertexColors: THREE.VertexColors
	} );

	this.cubeMesh = new THREE.Mesh( this.cubeGeometry, this.cubeMaterial );

	this.randomizer = new THREE.Randomizer();

	this.cubes = [];

	this.camera_distance = .9;
	camera.position.set( 0, 0, this.camera_distance );
	this.camera_focus = new THREE.Vector3();

	var mix = function(a,b,x)
	{
		return a + (b-a)*x;
	};

	this.init = function ( parameters ) {

		this.phase = parameters.phase;


		this.lasttime = 0;

		var closed_left_eye = 0.75;
		var closed_right_eye = 0.8;
		var bend_back = 1.;



		function vec3(x,y,z) {
			if (y===undefined && z===undefined)
				return x.clone();
			else
				return new THREE.Vector3(x,y,z);
		};

		var a = (this.phase-0.5)/6.0*2*Math.PI;
		this.camera_focus = vec3(Math.cos(a),0.2,Math.sin(a));




		function applyVertexColors( g, c ) {
			g.faces.forEach( function( f ) {
				var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
				for( var j = 0; j < n; j ++ ) {
					f.vertexColors[ j ] = c;
				}
			} );
		}

		var randomizer = this.randomizer;
		var a = randomizer.randFloat(0,1);
		
		var rnd = function(a,b) {
			if (a===undefined && b===undefined)
				return randomizer.randFloat(-1,1);
			else if (b===undefined)
				return randomizer.randFloat(0,a);
			return randomizer.randFloat(a,b);
		};

		var numCubes = this.numCubes;
		var cubesize = function() {
			return 2./numCubes*(1.+0.5*rnd());
		};

		var color = new THREE.Color();
		var p = new THREE.Vector3();
		var rotation = new THREE.Euler();
		var scale = new THREE.Vector3();
		var startPosition = p.clone();
		var endPosition = p.clone();

		// build voxels
		for( var ix = 0; ix <= this.numCubes; ix++ )
		for( var iy = 0; iy <= this.numCubes; iy++ )
		for( var iz = 0; iz <= this.numCubes; iz++ )
		{
			p.x = (ix/this.numCubes)*2-1;
			p.y = (iy/this.numCubes)*2-0.5;
			p.z = (iz/this.numCubes)*2-1;

			var d = BirdieBird.scenedist(p);
			if (d[3] > 0.01 || d[3] < -cubesize())
				continue;

			p.y -= 0.5;
			var angle = (Math.atan2(p.x,p.z) + 2*Math.PI) % (2*Math.PI);

			startPosition.copy(p);
			endPosition.copy(p);
			//p.y += 5;
			endPosition.y -= -2;
			endPosition.x += Math.cos(angle+rnd()*0.5)*4;
			endPosition.z += Math.sin(angle+rnd()*0.5)*4;
			//startPosition.y = p.y - (5+p.y)*(1+rnd(1));

			rotation.x = rnd() * 0.01*Math.PI;
			rotation.y = angle;
			rotation.z = rnd() * 0.01*Math.PI;

			scale.x = cubesize();
			scale.y = cubesize();
			scale.z = cubesize();

			var cube = this.cubeMesh.clone();
			//cube.geometry = this.cubeMesh.geometry.clone();
			cube.endPosition = endPosition.clone();
			cube.startPosition = startPosition.clone();
			cube.position.copy(cube.startPosition);
			cube.rotation.copy(rotation);
			cube.quaternion.setFromEuler( rotation );
			cube.scale.copy(scale);

			cube.material = this.cubeMesh.material.clone();
			cube.material.color.setRGB(d[0],d[1],d[2]);
			cube.material.ambient.setRGB(d[0],d[1],d[2]);

			//applyVertexColors( cube.geometry, color.setRGB(d[0],d[1],d[2]));

			this.cubes.push( cube );
			scene.add( cube );
		}
	};

	var animate_p = new THREE.Vector3();
	this.animate = function (t, perc, t_global )
	{
		perc = perc*4;
		var inc = t-this.lasttime;
		this.lasttime = t;
		//scene.rotation.y = t;
		//scene.quaternion.setFromEuler( scene.rotation );
		//scene.matrix.compose(scene.position,scene.quaternion,scene.scale);
		var a = 3.14+Math.sin(.1*t_global);

		camera.position.set( this.camera_distance*Math.sin(a), 0, this.camera_distance*Math.cos(a) );
		var sp = scene.position.clone();
		camera.lookAt(sp);

		for(var i = 0, l=this.cubes.length; i < l; i++)
		{
			var cube = this.cubes[i];

			var x = perc - cube.startPosition.y - 0.5;
			cube.visible = x>0 & x<1;
			animate_p.x = mix(cube.startPosition.x, cube.endPosition.x, x);
			animate_p.y = cube.startPosition.y + 3.7*x-12*x*x;
			animate_p.z = mix(cube.startPosition.z, cube.endPosition.z, x);
			cube.position.copy(animate_p);
			cube.rotation.x = 10*animate_p.x;
			cube.rotation.y = 10*animate_p.y;
			cube.rotation.z = 10*animate_p.z;
			cube.quaternion.setFromEuler( cube.rotation );
		}
	};

	this.update = function ( t, perc, t_global ) {

		this.animate( t, perc, t_global );

		if ( this.renderToTexture )
			renderer.render( scene, camera, this.fbo, this.clearBuffer );
		else
			renderer.render( scene, camera );

	};

};