/**
 * Cloud 9
 * staalebk
 */
THREE.House = function(width, length, height, angle) {

	this.roofAngle = 90-angle;

	this.ApexHeight = width/2 / Math.tan(deg2rad(this.roofAngle));
	this.roofLength = width/2 / Math.sin(deg2rad(this.roofAngle)) + width*0.1;

	this.chimneyY = height + this.ApexHeight/2;
	this.chimneyHeight = height/2;

	this.windowWidth = Math.min(height,width)/2;

	//seed = seed || 1;

	THREE.Object3D.call(this);

	this.type = 'House';

	//randSeed(seed);

	// == on floats.. nope
	this.nearEnough = function(x, y)
	{
		if (x >= y-0.001 && x <= y+0.001)
			return true;
		return false;
	}

	this.wallMat = new THREE.MeshLambertMaterial({
		//ambient: 0xADFFB2,
		color: 0x9B9763,
		//emissive: 0x099723,
		shading: THREE.FlatShading,
		side: THREE.DoubleSide,
		wireframe: false,
		map: tex.wood_tile
	});

	this.woodMat = new THREE.MeshLambertMaterial({
		//ambient: 0xADFFB2,
		color: 0x713B00,
		//emissive: 0x099723,
		shading: THREE.FlatShading,
		side: THREE.DoubleSide,
		wireframe: false,
		map: tex.perlintile_low
	});

	this.windowMat = new THREE.MeshPhongMaterial({
		//ambient: 0xADFFB2,
		color: 0x30AEBE,
		//emissive: 0x099723,
		shading: THREE.FlatShading,
		side: THREE.DoubleSide,
		wireframe: false
	});

	this.roofMat = new THREE.MeshLambertMaterial({
		//ambient: 0xADFFB2,
		color: 0x402300,
		//emissive: 0x099723,
		shading: THREE.FlatShading,
		side: THREE.DoubleSide,
		wireframe: false,
		map: tex.rooftiles
	});

	this.chimneyMat = new THREE.MeshLambertMaterial({
		//ambient: 0xADFFB2,
		color: 0x402300,
		//emissive: 0x099723,
		shading: THREE.FlatShading,
		side: THREE.DoubleSide,
		wireframe: false,
		map: tex.brick_tile
	});

	// because == on floats...
	this.closeEnough = function(x, y)
	{
		if (x >= y-0.001 && x <= y+0.001)
			return true;
		return false;
	}

	this.createWall = function(width, height, depth, endwall, win)
	{
		var w = new THREE.Object3D();

		var wallGeo = new THREE.BoxGeometry(width, height, depth, 2,2,1);

		
		for (var i=0; i<wallGeo.vertices.length; i++)
		{
			if (endwall)
			{
				if (this.closeEnough(wallGeo.vertices[i].y, height/2) && this.closeEnough(wallGeo.vertices[i].x, 0))
				{
					wallGeo.vertices[i].y += this.ApexHeight;
				}
			}

			// gjør så veggene stikker ned i bakken.. no floating houses
			if (this.closeEnough(wallGeo.vertices[i].y, -height/2))
			{
				wallGeo.vertices[i].y -= height/3;
			}

		}
		wallGeo.computeFaceNormals();
		wallGeo.computeVertexNormals();
		


		if (win)
		{
			var windowDepth = this.windowWidth/10;
			
			// Window frame
			var windowTop = new THREE.Mesh(new THREE.BoxGeometry(this.windowWidth, windowDepth, windowDepth, 2,2,2), this.woodMat);
			windowTop.position.y += this.windowWidth/2;
			windowTop.position.y += height/2;
			windowTop.position.z += depth/1.8;

			var windowBottom = new THREE.Mesh(new THREE.BoxGeometry(this.windowWidth, windowDepth, windowDepth, 2,2,2), this.woodMat);
			windowBottom.position.y -= this.windowWidth/2;
			windowBottom.position.y += height/2;
			windowBottom.position.z += depth/1.8;

			var windowHorizontal = new THREE.Mesh(new THREE.BoxGeometry(this.windowWidth, windowDepth, windowDepth/1.5, 2,2,2), this.woodMat);
			//windowBottom.position.y -= this.windowWidth/2;
			windowHorizontal.position.y += height/2;
			windowHorizontal.position.z += depth/1.8;

			var windowLeft = new THREE.Mesh(new THREE.BoxGeometry(windowDepth, this.windowWidth - windowDepth, windowDepth, 2,2,2), this.woodMat);
			windowLeft.position.x -= (this.windowWidth/2 - windowDepth/2);
			windowLeft.position.y += height/2;
			windowLeft.position.z += depth/1.8;

			var windowRight = new THREE.Mesh(new THREE.BoxGeometry(windowDepth, this.windowWidth - windowDepth, windowDepth, 2,2,2), this.woodMat);
			windowRight.position.x += (this.windowWidth/2 - windowDepth/2);
			windowRight.position.y += height/2;
			windowRight.position.z += depth/1.8;

			var windowVertical = new THREE.Mesh(new THREE.BoxGeometry(windowDepth, this.windowWidth - windowDepth, windowDepth/1.5, 2,2,2), this.woodMat);
			//windowVertical.position.x += (this.windowWidth/2 - windowDepth/2);
			windowVertical.position.y += height/2;
			windowVertical.position.z += depth/1.8;
			
			// "glass"
			var windowGlass = new THREE.Mesh(new THREE.BoxGeometry(this.windowWidth - windowDepth, this.windowWidth, windowDepth/2, 2,2,2), this.windowMat);
			windowGlass.position.y += height/2;
			windowGlass.position.z += depth/1.8;
			
			w.add(windowTop);
			w.add(windowBottom);
			w.add(windowHorizontal);
			w.add(windowLeft);
			w.add(windowRight);
			w.add(windowVertical);
			w.add(windowGlass);
		} else
		{
			var doorHeight = height/4*3;
			var doorWidth = width/3;
			var door = new THREE.Mesh(new THREE.BoxGeometry(doorWidth, doorHeight, depth, 2,2,2), this.woodMat);
			door.position.y += doorHeight/2;
			door.position.x += doorWidth/2;
			door.position.z += depth/4;

			w.add(door);
		}

		wall = new THREE.Mesh(wallGeo, this.wallMat);
		wall.position.y += height/2;

		w.add(wall);

		return w;
	}

	this.createRoof = function(width, length, depth, left)
	{
		var roofGeo = new THREE.BoxGeometry(width, depth, length, 2,2,2);
		
		var s = left ? 1.7 : 1.5;
		var beamGeoFront = new THREE.BoxGeometry(width*1.15, depth*s, depth*s, 2,2,2);
		var s = left ? 1.5 : 1.7;
		var beamGeoBack = new THREE.BoxGeometry(width*1.15, depth*s, depth*s, 2,2,2);

		for (var i=0; i<roofGeo.vertices.length; i++)
		{
			if (this.closeEnough(roofGeo.vertices[i].x, 0))
			{
				roofGeo.vertices[i].y -= depth/2;
				beamGeoFront.vertices[i].y -= depth/2;
				beamGeoBack.vertices[i].y -= depth/2;
			}
		}

		var m = new THREE.Matrix4();
		if (left)
		{
			m.makeTranslation(-width/2,0,0);
			//m.makeTranslation(width/2,0,0);
		} else
		{
			m.makeTranslation(width/2,0,0);
			//m.makeTranslation(-width/2,0,0);
		}
		roofGeo.applyMatrix(m);

		beamGeoFront.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,-length/2));
		beamGeoFront.applyMatrix(m);

		beamGeoBack.applyMatrix(new THREE.Matrix4().makeTranslation(0,0,length/2));
		beamGeoBack.applyMatrix(m);

		roofGeo.computeFaceNormals();
		roofGeo.computeVertexNormals();

		var roof = new THREE.Object3D;

		roof.add(new THREE.Mesh(roofGeo, this.roofMat));
		roof.add(new THREE.Mesh(beamGeoFront, this.woodMat));
		roof.add(new THREE.Mesh(beamGeoBack, this.woodMat));

		//var roofPlate = new THREE.Mesh(roofGeo, this.roofMat);

		//var roofBeamL = new THREE.Mesh(beamGeo);

		return roof;

	}

	var getCloudGeometry = function(x, y, z) {
		var cloud = new THREE.BoxGeometry(x, y, z);
		cloud.mergeVertices();
		var modifier = new THREE.SubdivisionModifier(1);
		modifier.modify(cloud);
		return cloud;
	}

	randSeed(123456);
	this.poofSize = (width+height)/2 * 0.3;
	this.poofNum = 6;
	this.poofs = [];
	for (var i=0; i < this.poofNum; i++)
	{
		var params = {
			rotX: randGet(100),
			rotY: randGet(100),
			rotZ: randGet(100),
		}
		var smokeMat = new THREE.MeshLambertMaterial({
			ambient: 0x999999,
			color: 0xaaaaaa,
			emissive: 0x222222,
			shading: THREE.FlatShading,
			transparent: true
		});

		var poofGeo = getCloudGeometry(this.poofSize, this.poofSize, this.poofSize);
		var poof = new THREE.Mesh(poofGeo, smokeMat);
		poof.customOverrideMaterial = new THREE.MeshBasicMaterial({color:0x000000});
		poof.position.x = width/4;
		poof.params = params;
		this.poofs.push(poof);
		this.add(this.poofs[i]);
	}


	var mat = new THREE.MeshLambertMaterial({
		ambient: 0xADFFB2,
		color: 0x099723,
		emissive: 0x099723,
		shading: THREE.FlatShading,
		side: THREE.DoubleSide,
		wireframe: true
	});

	// Three.js to csg
	// var geometryCsg    = THREE.CSG.toCSG(geometryThree);

	// Csg to three.js
	// var geometryThree  = THREE.CSG.fromCSG(geometryCsg);


	//this.wall = this.createWall(7,5,1, true, false);
	//this.add(this.wall);

	var wallDepth = width/16;

	this.frontWall = this.createWall(width, height, wallDepth, true, false);
	this.frontWall.position.z += length/2;

	this.backWall = this.createWall(width, height, wallDepth, true, true);
	this.backWall.position.z -= length/2;
	this.backWall.rotation.y = deg2rad(180);
	

	this.leftWallMesh = this.createWall(length - wallDepth, height, wallDepth, false, true);
	this.leftWallMesh.rotation.y = deg2rad(270);
	this.leftWall = new THREE.Object3D();
	this.leftWall.add(this.leftWallMesh);
	this.leftWall.position.x -= (width/2 - wallDepth/2);

	this.rightWallMesh = this.createWall(length -wallDepth, height, wallDepth, false, true);
	this.rightWallMesh.rotation.y = deg2rad(90);
	this.rightWall = new THREE.Object3D();
	this.rightWall.add(this.rightWallMesh);
	this.rightWall.position.x += (width/2 - wallDepth/2);


	this.leftRoof = this.createRoof(this.roofLength, length*1.1, wallDepth*1.2, true);
	this.rightRoof = this.createRoof(this.roofLength, length*1.1, wallDepth*1.2, false);

	var roofBeamGeo = new THREE.BoxGeometry(wallDepth*2.5, wallDepth*2.5, length*1.3);
	this.roofBeam = new THREE.Mesh(roofBeamGeo, this.woodMat);
	//this.roofBeam.rotation.z = deg2rad(45);


	var chimneyGeo = new THREE.BoxGeometry(width/8, this.chimneyHeight, width/8, 1,1);
	//var chimneyGeo = new THREE.BoxGeometry(10,10,10, 1,1);
	this.chimney = new THREE.Mesh(chimneyGeo, this.chimneyMat);
	this.chimney.position.x = width/4;


	this.add(this.frontWall);
	this.add(this.backWall);
	this.add(this.leftWall);
	this.add(this.rightWall);

	this.add(this.leftRoof);
	this.add(this.rightRoof);
	this.add(this.roofBeam);
	this.add(this.chimney);


	this.animate = function(n, t)
	{	

		var deg = n*90;

		//this.wall.rotation.x = deg2rad(n);


		var v1 = getVal('var1'); // wallside
		var v2 = getVal('var2'); // wallfront
		var v3 = getVal('var3'); // height
		var v4 = getVal('var4'); // raiseroof
		var v5 = getVal('var5'); // roofwidth
		var v6 = getVal('var6'); // roof fold
		var v7 = getVal('var7');


		/*
			var wallSideN = easeOne('easeOutBounce',segmentTransition(0,0.25, n));
			var wallFrontN = easeOne('easeOutBounce',segmentTransition(0.25,0.5, n));
			var heightOffset = (1-easeOne('easeInOutElastic',segmentTransition(0,0.75, n)))*-height/3;
		*/

		// Define main animation sequence. house first, then chimney and smoke
		var houseN = segmentTransition(0.0, 0.5, n);
		var smokeN = segmentTransition(0.5, 1.0, n);

		// Define house animation sequence
		var wallSideN =       segmentTransition(0.0,   0.41,  houseN);
		var wallFrontN =      segmentTransition(0.33,  0.66,  houseN);
		var heightOffset = (1-segmentTransition(0.0,   0.41,  houseN)) * -height/3;//*-height/3);
		var roofRaiseN =      segmentTransition(0.54,  1.0,   houseN);
		var roofWidthN =      segmentTransition(0.875, 0.958, houseN);
		var roofFoldN =       segmentTransition(0.79,  1.0,   houseN);

		roofRaiseN = easeOne('easeInOutBack', roofRaiseN);		
		wallFrontN = easeOne('easeOutBounce',wallFrontN);
		wallSideN = easeOne('easeOutBounce',wallSideN);


		// Smoke animation sequence
		var chimneyN = segmentTransition(0.0, 0.5, smokeN);
		var poofN = segmentTransition(0.3, 1, smokeN);

		chimneyN = easeOne('easeOutCubic', chimneyN);


		this.frontWall.rotation.x = deg2rad(-90+wallFrontN*90);
		this.frontWall.scale.set(1, 0.5+wallFrontN/2, 1);
		this.frontWall.position.y = +heightOffset;

		this.backWall.rotation.x = deg2rad(90-wallFrontN*90);
		this.backWall.scale.set(1, 0.5+wallFrontN/2, 1);
		this.backWall.position.y = +heightOffset;

		this.leftWall.rotation.z = deg2rad(-90+wallSideN*90);
		this.leftWall.scale.set(1, 0.5+wallSideN/2, 1);
		this.leftWall.position.y = +heightOffset;

		this.rightWall.rotation.z = deg2rad(+90-wallSideN*90);
		this.rightWall.scale.set(1, 0.5+wallSideN/2, 1);
		this.rightWall.position.y = +heightOffset;


		if (roofRaiseN > 0.0000001)
		{
			this.roofBeam.visible = true;
			this.leftRoof.visible = true;
			this.rightRoof.visible = true;

			this.leftRoof.position.y = -height + (height+this.ApexHeight + height) * roofRaiseN;
			this.leftRoof.rotation.z = deg2rad(morph(-90, 90-this.roofAngle, roofFoldN));
			this.leftRoof.scale.z = 0.8 + roofWidthN*0.2;

			this.rightRoof.position.y = -height + (height+this.ApexHeight + height) * roofRaiseN;
			this.rightRoof.rotation.z = deg2rad(morph(90, -(90-this.roofAngle), roofFoldN));
			this.rightRoof.scale.z = 0.8 + roofWidthN*0.2;

			this.roofBeam.position.y = -height + (height+this.ApexHeight + height) * roofRaiseN;
			this.roofBeam.scale.z = 0.8 + roofWidthN*0.2;
		} else
		{
			this.roofBeam.visible = false;
			this.leftRoof.visible = false;
			this.rightRoof.visible = false;
		}

		if (chimneyN > 0.0000001)
		{
			this.chimney.visible = true;
			this.chimney.position.y = this.chimneyY - (1-chimneyN) * this.chimneyHeight;
		} else
		{
			this.chimney.visible = false;
		}
		

		for (var i=0; i<this.poofs.length; i++)
		{
			/*

			var iPoof = ((t + i)%this.poofNum)/this.poofNum;
			var psc = easeOne('easeOutSine',iPoof) + 0.0000001;
			this.poofs[i].position.y = this.chimneyY + this.chimneyHeight/2 + this.poofSize * psc * this.poofNum * 0.7;
			this.poofs[i].scale.set(psc, psc, psc);
			this.poofs[i].rotation.x = this.poofs[i].params.rotX * t;
			this.poofs[i].rotation.y = this.poofs[i].params.rotY * t;
			this.poofs[i].rotation.z = this.poofs[i].params.rotZ * t;
*/

			var iPoof = ((t + i)%this.poofNum)/this.poofNum;
			var psc = easeOne('easeOutSine',iPoof) + 0.0000001;
			this.poofs[i].position.y = this.chimneyY + this.chimneyHeight/2 + this.poofSize * psc * this.poofNum * 0.7;
			this.poofs[i].scale.set(psc * poofN + 0.0000000000001, psc * poofN + 0.0000000000001, psc * poofN + 0.0000000000001);
			this.poofs[i].rotation.x = this.poofs[i].params.rotX * t;
			this.poofs[i].rotation.y = this.poofs[i].params.rotY * t;
			this.poofs[i].rotation.z = this.poofs[i].params.rotZ * t;

			
			var e = easeOne('easeInCubic',iPoof);

			this.poofs[i].material.opacity = (1-e) * poofN;

			if (poofN > 0.00000000000001)
			{
				this.poofs[i].rotation.visible = true;
			} else
			{
				this.poofs[i].rotation.visible = false;
			}
		}
		

	}

};

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