// Wall with pilars poking out of it.

THREE.Cave = function(radius) {
	THREE.Object3D.call(this);

	this.type = 'Cave';

	this.radius = radius;

	this.wiggleCoordinates = function(geo, dist, seed)
	{
		for (var i=0; i < geo.vertices.length; i++)
		{
			geo.vertices[i].x += (Math.random()-0.5)*dist;
			geo.vertices[i].y += (Math.random()-0.5)*dist;
			geo.vertices[i].z += (Math.random()-0.5)*dist;
		}
		geo.computeFaceNormals();
		geo.computeVertexNormals();
	}


	this.caveWallMat = new THREE.MeshLambertMaterial({
		color: 0x7E430E,
		//color: 0x433242,
		shading: THREE.FlatShading,
		//side: THREE.BackSide,
		wireframe: false
	});
	
	var helperMatRed = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});

	var caves = [
		{
			position: new THREE.Vector3(0,0,-500),
			radius: 20
		},				
		{
			position: new THREE.Vector3(0,0,0),
			radius: radius
		}				
	];

/*
	var tunnelPoints = [
		new THREE.Vector3(-500,0,0),

		new THREE.Vector3(-120,0,0),
		new THREE.Vector3(-100,0,0),
		new THREE.Vector3(0,0,0),
		new THREE.Vector3(100,0,0),
		new THREE.Vector3(120,0,0),

		new THREE.Vector3(500,0,0),
	];
*/
		var tunnelPoints = [
		new THREE.Vector3(0,0,-500),

		new THREE.Vector3(0,0,-400),

		new THREE.Vector3(10,30,-250),
		new THREE.Vector3(0,20,-200),

		new THREE.Vector3(0,0,-150),
		new THREE.Vector3(0,0,-120),
		new THREE.Vector3(0,0,0),
		new THREE.Vector3(0,0,120),
		new THREE.Vector3(0,0,150),
		
		new THREE.Vector3(0,-20,200),
		new THREE.Vector3(20,-30,250),
		new THREE.Vector3(-20,30,300),

		new THREE.Vector3(0,0,400),

		new THREE.Vector3(0,0,500),
	];

	// Creating a tunnel in the cave system
	this.tunnelSpline = new THREE.SplineCurve3(tunnelPoints);

	// Camera spline
	var cameraPoints = [];
	for (var i=0; i<tunnelPoints.length; i++)
	{
		cameraPoints.push(tunnelPoints[i]);
	}
	this.cameraSpline = new THREE.SplineCurve3(cameraPoints);

	var splineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
	//var spline = new THREE.Mesh();

	var geometry = new THREE.Geometry();
	
	var splinePoints = this.cameraSpline.getPoints(100);

	for(var i = 0; i < splinePoints.length; i++){
		geometry.vertices.push(splinePoints[i]);  
	}

	//var line = new THREE.Line(geometry, splineMaterial);
	//this.add(line);


	this.tunnelGeometry = new THREE.TubeGeometry (
		this.tunnelSpline,
		300, // segments
		5, // radius
		11, //radius segments
		false // open ended
	);


	this.wiggleCoordinates(this.tunnelGeometry, 1, 3434);

	
	for (var c=0; c<caves.length; c++)
	{
		for (var i=0; i<this.tunnelGeometry.vertices.length; i++)
		{
			var v = this.tunnelGeometry.vertices[i];

			// Find distance to center of cave.
			var dist = caves[c].position.distanceTo(v);
			if (dist <= caves[c].radius)
			{
				var angle = new THREE.Vector3().subVectors(v, caves[c].position).normalize();

				v.x = caves[c].position.x + angle.x * caves[c].radius;
				v.y = caves[c].position.y + angle.y * caves[c].radius;
				v.z = caves[c].position.z + angle.z * caves[c].radius;
			}
		}
	}

	flipNormals(this.tunnelGeometry);
	this.tunnelGeometry.computeFaceNormals();
	this.tunnelGeometry.computeVertexNormals();
	

	/*for (var i=0; i<tunnelGeometry.faces.length; i++)
	{
		var f = tunnelGeometry.faces[i];
		var vert = [f.a, f.b, f.c];

		for(var vi=0; vi<vert.length; vi++)
		{
			v = tunnelGeometry.vertices[vi];

		}
	}*/


	var debugMaterial = new THREE.MeshBasicMaterial({color:0xBC760E, wireframe:true});
	var debugMesh = new THREE.Mesh(this.tunnelGeometry, debugMaterial);
	//this.scene.add(debugMesh);

	this.caveMesh = new THREE.Mesh(this.tunnelGeometry, this.caveWallMat);
	this.add(this.caveMesh);


	// Add a flying pig.
	this.pig = new THREE.Pig({center:true});
	this.pig.scale.set(0.55, 0.55, 0.55);
	this.pig.position.set(1000,1000,1000);
	this.add(this.pig);


	this.orbitCamY = 0;
	this.orbitCamRadius = 0;


	this.cameraVector = new THREE.Vector3(0,0,0);

	this.getCamOrbit = function(lat, lon, radius)
	{
		var cam_x = radius * Math.sin(lat)*Math.cos(lon);
		var cam_z = radius * Math.sin(lat)*Math.sin(lon);
		var cam_y = radius * Math.cos(lat);

		var vec = new THREE.Vector3(cam_x, cam_y, cam_z);

		this.cameraVector.set(vec.x, vec.y, vec.z);

		return vec;
	};

	this.getOrbit = function(lat, lon, radius)
	{
		var cam_x = radius * Math.sin(lat)*Math.cos(lon);
		var cam_z = radius * Math.sin(lat)*Math.sin(lon);
		var cam_y = radius * Math.cos(lat);

		var vec = new THREE.Vector3(cam_x, cam_y, cam_z);

		return vec;
	};

	this.animatePig = function(n)
	{
		if(n < 0 || n > 100) {
			return;
		}
		var pigPos = this.cameraSpline.getPointAt(n/100);
		this.pig.position.set(pigPos.x, pigPos.y, pigPos.z);
		this.pig.rotation.set(n*0.8/4,n/4,n*1.2/4);
	}

	/*
		Call controlCamera() to get premade easy to use camera movements.

		var7 0-100: follow the spline
				var6 controls the lookAt point, also 0-100
		var7 >100: sherical coordinates. lookAt center.
			var7: lat
			var6: lon

		Camera offsets work like normal.

	*/

	this.controlCamera = function(camera)
	{
		var v7 = getVal('var7');
		var v6 = getVal('var6');

		var campos = new THREE.Vector3(0,0,0);
		var lookpos = new THREE.Vector3(0,0,0);

		if (v7 >= 0 && v7 <=100)
		{
			v6 = v6<0 ? 0 : (v6>100 ? 100 : v6);

			campos = this.cameraSpline.getPointAt(v7/100)
			lookpos = this.cameraSpline.getPointAt(v6/100)

		} else if (v7 > 100)
		{	
			if (v6 > 1000)
			{
				this.orbitCamRadius = getVal('var5');
				this.orbitCamY = getVal('var4');

				campos = this.getCamOrbit(deg2rad(v7-100), deg2rad(v6), this.radius-25);
				lookpos = this.getCamOrbit(deg2rad(v7-100), deg2rad(v6 + 45), this.orbitCamRadius);
				lookpos = new THREE.Vector3(lookpos.x, lookpos.y+this.orbitCamY, lookpos.z);
			} else
			{
				campos = this.getCamOrbit(deg2rad(v7-100), deg2rad(v6), this.radius-5);
				lookpos = new THREE.Vector3(0,0,0);	
			}
		}

		var camVector = new THREE.Vector3(campos.x + getVal('camx'), campos.y + getVal('camy'), campos.z + getVal('camz'));
		var lookVector = new THREE.Vector3(lookpos.x + getVal('cam2x'), lookpos.y + getVal('cam2y'), lookpos.z + getVal('cam2z'));

		camera.position.set(camVector.x, camVector.y, camVector.z);
		camera.lookAt(lookVector);
	}

};

THREE.Cave.prototype = Object.create(THREE.Object3D.prototype);
THREE.Cave.prototype.constructor = THREE.Cave;