var sphere1;
var mainCharacter;
var camera;

var playerMovement = 10;
var movementTime = 2;

var lumberMan;

var light;
var light2;
var light3;
var light4;

var weedArr = [];
var weed2Arr = [];
var weed3Arr = [];

var groupX = -70;
var groupY = 30;
var groupZ = -5;

var fish1;
var fish2;
var fish3;

var phase1 = 0;

//Initialize function
var init = function () {
	// TODO:: Do your initialization job
	console.log("init() called");
	
	// Fetch the canvas element from the HTML
	var canvas = document.querySelector("#renderCanvas");

	// Load BABYLON
	var engine = new BABYLON.Engine(canvas, true);
	
	// This function will create our world
	var createScene = function () {

	    // Creating the BABYLON scene
	    var scene = new BABYLON.Scene(engine);

	    // Change the scenes' background to black
	    scene.clearColor = new BABYLON.Color3(0, 0, 0);
	    
	    // Set the scenes' ambient color to a bit of blue
	    scene.ambientColor = new BABYLON.Color3(0, 0, 0.03);
	    
	    // Skybox - we need to create a skybox for our world
	    var skybox = BABYLON.Mesh.CreateBox("skyBox", 100.0, scene);
	      //skybox.infiniteDistance = true; // <-- with this you can make the skybox of infinite size
	    
	    // create material for the skybox
	    var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
		    skyboxMaterial.backFaceCulling = false;
		    skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("images/seabox/sea", scene);
		    skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
		    skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
		    skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
		    
		    skybox.material = skyboxMaterial;
		    
		    skybox.x = 1000;
		    
	   
        // this section creates lights for our scene - we have one hemispheric light and three omni lights
	        light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
		    light.intensity = .5;
		    
		    
		    light2 = new BABYLON.PointLight("Omni1", new BABYLON.Vector3(0, 0, 0), scene);
			light2.diffuse = new BABYLON.Color3(0, 0, 0.1);
			light2.specular = new BABYLON.Color3(1, 1, 1);
			light2.intensity = 2;
			
			
			light3 = new BABYLON.PointLight("Omni2", new BABYLON.Vector3(-15, -20, 40), scene);
			light3.diffuse = new BABYLON.Color3(0, 0, 0.1);
			light3.specular = new BABYLON.Color3(1, 1, 1);
			light3.intensity = 1;
			
			
			light4 = new BABYLON.PointLight("Omni3", new BABYLON.Vector3(35, -10, 35), scene);
			light4.diffuse = new BABYLON.Color3(0, 0, 0.1);
			light4.specular = new BABYLON.Color3(1, 1, 1);
			light4.intensity = 1;

	   
	 // Fog - this will help us hide the things that are really far from the camera
	    scene.fogMode = BABYLON.Scene.FOGMODE_LINEAR;
	    scene.fogColor = new BABYLON.Color3(0, 0, 0.01);
	    
	    scene.fogStart = 20.0;
	    scene.fogEnd = 78.0;
	    
	 /////// SPRITES /////// 
	    
	 // Create a sprite manager for our diver
	    var spriteManagerDiver = new BABYLON.SpriteManager("diverMgr", "images/diverSprite.png", 1, 512, scene);
	        mainCharacter = new BABYLON.Sprite("diver", spriteManagerDiver);
	    	mainCharacter.position.y = -2;
	    	mainCharacter.position.z = -0.5;
	    	mainCharacter.size = 6;
	    	mainCharacter.renderingGroupId = 0;
	    	mainCharacter.playAnimation(0, 13, true, 100);    	
	    	
	 // Create a sprite manager for the first weeds
	    var spriteManagerWeed1 = new BABYLON.SpriteManager("weedMgr1", "images/glon.png", 300, 256, scene);
		
	 // here we create weeds on the sea floor   
		    for (var i=0; i < 300; i++) {
		    
		    var weed = new BABYLON.Sprite("weed1", spriteManagerWeed1);
		    	
		    	weed.renderingGroupId = 0;
			 	weed.size = getRandomNumber(5,30);
			 	
			 	weed.position.x = getRandomNumber(-50,50);
			 	weed.position.y = getRandomNumber(-44,-40);
			 	weed.position.z = getRandomNumber(-50,50);
		    	
			 	var rndSide = Math.round(getRandomNumber(0,1));
			
				 	if (rndSide == 0) {
				 		weed.invertU = -1;
				 	}
				 	else
				 	{
				 		weed.invertU = 0;
				 	}
			 	
			 	
			    weed.playAnimation(0, 29, true, 100);
			    
			    weedArr.push(weed);
		    
		    }
		

	    // Create a sprite manager for the second weeds
	    var spriteManagerWeed2 = new BABYLON.SpriteManager("weedMgr2", "images/seaweed2.png", 100, 256, scene);
		
		    for (var i=0; i < 100; i++) {
		    
		    var weed2 = new BABYLON.Sprite("weed2", spriteManagerWeed2);
		    	
		    	weed2.renderingGroupId = 0;
			 	weed2.size = getRandomNumber(3,10);
			 	
			 	weed2.position.x = getRandomNumber(-50,50);
			 	weed2.position.y = getRandomNumber(-45,-44);
			 	weed2.position.z = getRandomNumber(-50,50);
		    	
			 	var rndSide = Math.round(getRandomNumber(0,1));
			
				 	if (rndSide == 0) {
				 		weed2.invertU = -1;
				 	}
				 	else
				 	{
				 		weed2.invertU = 0;
				 	}
		
			    weed2Arr.push(weed2);
	    
	    }

	    // Create a sprite manager for the third weeds
	    var spriteManagerWeed3 = new BABYLON.SpriteManager("weedMgr3", "images/seaweed3.png", 100, 256, scene);
		
		    for (var i=0; i < 100; i++) {
		    
		    var weed3 = new BABYLON.Sprite("weed3", spriteManagerWeed3);
		    	
		    	weed3.renderingGroupId = 0;
			 	weed3.size = getRandomNumber(3,10);
			 	
			 	weed3.position.x = getRandomNumber(-50,50);
			 	weed3.position.y = getRandomNumber(-45,-44);
			 	weed3.position.z = getRandomNumber(-50,50);
		    	
			var rndSide = Math.round(getRandomNumber(0,1));
			 
			 	if (rndSide == 0) {
			 		weed3.invertU = -1;
			 	}
			 	else
			 	{
			 		weed3.invertU = 0;
			 	}
			 	
			    weed3Arr.push(weed3);
		    
		    }

	    // FISH 1 sprite
	    var spriteManagerFish1 = new BABYLON.SpriteManager("Fish1", "images/red_fish.png", 1, 256, scene);
		
		    fish1 = new BABYLON.Sprite("fish1", spriteManagerFish1);
		    fish1.size = getRandomNumber(2,5);
			 	
		    fish1.position.x = groupX;
		    fish1.position.y = groupY;
		    fish1.position.z = groupZ;
		    
		    fish1.invertU = -1;
		    
		    fish1.playAnimation(0, 19, true, 100);
	    
		// FISH 2 sprite
	    var spriteManagerFish2 = new BABYLON.SpriteManager("Fish2", "images/blue_fish.png", 1, 256, scene);
		
		    fish2 = new BABYLON.Sprite("fish2", spriteManagerFish2);
		    fish2.size = getRandomNumber(2,5);
			 	
		    fish2.position.x = groupX - 2;
		    fish2.position.y = groupY + 2;
		    fish2.position.z = groupZ +2;
		   
		    fish2.invertU = -1;
		    
		    fish2.playAnimation(0, 19, true, 100);
		    
	    // FISH 3 sprite
	    var spriteManagerFish3 = new BABYLON.SpriteManager("Fish3", "images/yellow_fish.png", 1, 256, scene);
			
		    fish3 = new BABYLON.Sprite("fish3", spriteManagerFish3);
		    fish3.size = getRandomNumber(2,5);
			 	
		    fish3.position.x = groupX + 3;
		    fish3.position.y = groupY + 1;
		    fish3.position.z = groupZ - 1;
	   
		    fish3.invertU = -1;
		    
			fish3.playAnimation(0, 19, true, 100);
		 
		// we need an invisible 3D DUMMY object (in our case sphere1) which to we will attach othere objects	
	    var material = new BABYLON.StandardMaterial("material", scene);
	        sphere1 = BABYLON.Mesh.CreateSphere("Sphere1", 32, 3, scene);	
	    
	        sphere1.isVisible = false; // since it is a dummy object we do not want it to be visible
	
	    /////// CAMERA /////// 
	        
	    // we need a camera for our scene, in our case a follow type camera 
	     camera = new BABYLON.FollowCamera("FollowCam", new BABYLON.Vector3(0, 20, -5), scene);
	     camera.target = sphere1; // target any mesh or object with a "position" Vector3
	    
	     camera.radius = 20; // how far from the object to follow
	     camera.heightOffset = 8; // how high above the object to place the camera
	     camera.rotationOffset = 180; // the viewing angle
	     camera.cameraAcceleration = 0.01 // how fast to move
	     camera.maxCameraSpeed = 20 // speed limit
	    
	     scene.activeCamera = camera;
	     
	 /////// PARTICLES /////// 
	    
	 // Create the particle system (we want to have bubbles underwater going out from our diver ain't we?)
	    var particleSystem = new BABYLON.ParticleSystem("particles", 2000, scene);

	    // we need to set the texture of each particle
	    particleSystem.particleTexture = new BABYLON.Texture("images/bubble.png", scene);

	    // now is the time to set the bounds for the particles
	    particleSystem.emitter = sphere1; // specify the emitter
	    particleSystem.minEmitBox = new BABYLON.Vector3(-1, 1, 0); // Start
	    particleSystem.maxEmitBox = new BABYLON.Vector3(1, 2, 0); // End

	    // Colors of the emitted particles
	    particleSystem.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
	    particleSystem.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
	    particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);

	    // the size of each particle
	    particleSystem.minSize = 0.3;
	    particleSystem.maxSize = 0.8;

	    // the life time of each particle
	    particleSystem.minLifeTime = 0.3;
	    particleSystem.maxLifeTime = 1.5;

	    // the emission rate of the particles
	    particleSystem.emitRate = 50;

	    // Blend mode : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
	    particleSystem.blendMode = BABYLON.ParticleSystem.BLENDMODE_ONEONE;

	    // we need to set the gravity of all the particles
	    particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);

	    // the direction of each particle after it has been emitted
	    particleSystem.direction1 = new BABYLON.Vector3(0, 15, 0);
	    particleSystem.direction2 = new BABYLON.Vector3(0, 15, 0);
	    
	    // Angular speed set in radians
	    particleSystem.minAngularSpeed = 0;
	    particleSystem.maxAngularSpeed = Math.PI;

	    // Speed of the particles
	    particleSystem.minEmitPower = 1;
	    particleSystem.maxEmitPower = 3;
	    particleSystem.updateSpeed = 0.005;

	    // Initialize the particle system
	    particleSystem.start();
	    
	    // Create the ground for our sea floor.
	    var groundMaterial = new BABYLON.StandardMaterial("groundTex", scene);
	    	groundMaterial.diffuseTexture = new BABYLON.Texture("images/floor.png", scene);

	    // generate a mesh using a loaded from JPG file height map
	    var ground = BABYLON.Mesh.CreateGroundFromHeightMap("groundHeight", "images/ground.jpg", 100, 100, 250, 0, 10, scene, false);
	    	ground.material = groundMaterial;
	    	
	    	ground.position.y = -48;
	    	
	    // Create the second particle system (the random bubbles in the water)
	    var particleSystem2 = new BABYLON.ParticleSystem("particles2", 2000, scene);

	    particleSystem2.particleTexture = new BABYLON.Texture("images/bubble.png", scene);

	    particleSystem2.emitter = ground; 
	    particleSystem2.minEmitBox = new BABYLON.Vector3(-50, -50, -50); 
	    particleSystem2.maxEmitBox = new BABYLON.Vector3(50, 100, 50); 

	    particleSystem2.color1 = new BABYLON.Color4(0.7, 0.8, 1.0, 1.0);
	    particleSystem2.color2 = new BABYLON.Color4(0.2, 0.5, 1.0, 1.0);
	    particleSystem2.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.0);

	    particleSystem2.minSize = 0.1;
	    particleSystem2.maxSize = 0.8;

	    particleSystem2.minLifeTime = 0.5;
	    particleSystem2.maxLifeTime = 40;

	    particleSystem2.emitRate = 500;
	    particleSystem2.start();
	    
	    // HERE WE IMPORT AND POSITION AN EXTERNAL MESH TO THE BABYLON 3D ENGINE
	    
	    	BABYLON.SceneLoader.ImportMesh("", "3d/", "drwal.babylon", scene, function (newMeshes) {
	    	lumberMan = newMeshes[0];
	    	
	    	lumberMan.scaling.x = 3;
	    	lumberMan.scaling.y = 3;
	    	lumberMan.scaling.z = 3;
	    	
	    	lumberMan.rotation.x = 2*Math.PI;
	    	lumberMan.rotation.z = Math.PI/ 0.75;
	    	
	    	lumberMan.position.z = 35;
	    	lumberMan.position.y = -40;
	    	
	    	var shadowGenerator2 = new BABYLON.ShadowGenerator(1024, light);
		 		shadowGenerator2.getShadowMap().renderList.push(lumberMan);
		 		shadowGenerator2.getShadowMap().renderList.push(ground);
		 		shadowGenerator2.usePoissonSampling = true;
	    	
	    });
	    
	    // this function is a must, please don't touch it
	    return scene;

	  };  // the end of our scene creating function
	  
	  
	  /////////// CLICK HANDLERS AND STEERING OF OUR DIVER //////////////
	  
	  // the diver moving functions below use the immortal TweenMax library
	  
	  function moveLeft() {
		  TweenMax.to(sphere1.position, movementTime, {x:sphere1.position.x - playerMovement});
		  TweenMax.to(mainCharacter.position, movementTime, {x:mainCharacter.position.x - playerMovement});
		  mainCharacter.invertU = 1;
	  }
	  
	  function moveRight() {
		  TweenMax.to(sphere1.position, movementTime, {x:sphere1.position.x + playerMovement});
		  TweenMax.to(mainCharacter.position, movementTime, {x:mainCharacter.position.x + playerMovement});
		  mainCharacter.invertU = 0;
	  }
	  
	  function moveUp() {
		  TweenMax.to(sphere1.position, movementTime, {y:sphere1.position.y + playerMovement});
		  TweenMax.to(mainCharacter.position, movementTime, {y:mainCharacter.position.y + playerMovement});
	  }
	  
	  function moveDown() {
		  TweenMax.to(sphere1.position, movementTime, {y:sphere1.position.y - playerMovement});
		  TweenMax.to(mainCharacter.position, movementTime, {y:mainCharacter.position.y - playerMovement});
	  }
	  
	  function moveForward() {
		  TweenMax.to(sphere1.position, movementTime, {z:sphere1.position.z + playerMovement});
		  TweenMax.to(mainCharacter.position, movementTime, {z:mainCharacter.position.z + playerMovement});
	  }
	  
	  function moveBack() {
		  TweenMax.to(sphere1.position, movementTime, {z:sphere1.position.z - playerMovement});
		  TweenMax.to(mainCharacter.position, movementTime, {z:mainCharacter.position.z - playerMovement});
	  }
	  
	  
	  // set click and touch handlers for our screen
	  
	  window.addEventListener("touchstart", moveCharacterTouch, false);
	  window.addEventListener("click", moveCharacterClick, false);
	  
	  function moveCharacterTouch(event) {
		  
		  var touchX = event.touches[0].pageX;
		  var touchY = event.touches[0].pageY;
		  
		  console.log("X = " + touchX + ", Y = " + touchY);
		  
		  	  if (touchY > 460) {
				 if (Math.floor(sphere1.position.y > -35)) moveDown();
			  }
			  
			  if (touchY < 100) {
				  if (Math.floor(sphere1.position.y < 25)) moveUp();
			  }
			  
			  if (touchX < 100) {
				  if (Math.floor(sphere1.position.x > -35)) moveLeft();
			  }
			  
			  if (touchX > 240) {
				  if (Math.floor(sphere1.position.x < 35)) moveRight();
			  }
		  
	  }
	  
	  function moveCharacterClick(event) {
		  
		  var clickX = event.pageX;
		  var clickY = event.pageY;
		  
		  console.log("X = " + clickX + ", Y = " + clickY);
		  
		  if (clickY > 460) {
			 if (Math.floor(sphere1.position.y > -35)) moveDown();
		  }
		  
		  if (clickY < 100) {
			  if (Math.floor(sphere1.position.y < 25)) moveUp();
		  }
		  
		  if (clickX < 100) {
			  if (Math.floor(sphere1.position.x > -35)) moveLeft();
		  }
		  
		  if (clickX > 240) {
			  if (Math.floor(sphere1.position.x < 35)) moveRight();
		  }
	  }
	  
	  // now we create the scene actually invoking the createScnee function
	  var scene = createScene();
	  
	  // we need a render loop for our engine
	  engine.runRenderLoop(function () {
		
		  // here we create the sine phase for our fish
		  phase1 += 2;
		  if (phase1 > 360) phase1 = 0;
		  
		  // here we assign the second light to be set on the diver all the time
		  light2.position.x = sphere1.position.x;
		  light2.position.y = sphere1.position.y;
		  light2.position.z = sphere1.position.z;
		  
		  // here we position the first fish and make it wobble in the Y axis
		  fish1.position.x = groupX;
		  fish1.position.y = groupY + Math.sin((phase1 + 30) * Math.PI/180);
		  fish1.position.z = groupZ;
		  
		  // here we move the second fish and make it wobble in the Y axis
		  fish2.position.x = groupX - 2;
		  fish2.position.y = groupY + 2 + Math.sin(phase1 * Math.PI/180);
		  fish2.position.z = groupZ + 2;
		  
		  // here we move the third fish and make it wobble in the Y axis
		  fish3.position.x = groupX + 3;
		  fish3.position.y = groupY + Math.sin((phase1 + 70) * Math.PI/180);
		  fish3.position.z = groupZ - 1;

		  // here we move the group of our fishes
		  groupX += 0.05;
		  
		  // if the fishes go off screen bring them back to the beggining...
		  if (groupX > 70) {
			  groupX = -70;
	
			  // ... at a random Y position
			  groupY = getRandomNumber(-20,30);
	
		  }

	    scene.render(); // finally render the scene
	    
	  });
	
	  // Hear for the browser and canvas resize events
	  window.addEventListener("resize", function () {
		  
	    engine.resize();
	    
	  });
	  
	  // a simple helper function - give pseudo random numbers from a range
	  function getRandomNumber(min, max) {
		  
		    return Math.random() * (max - min) + min;
		    
	  }


	// add eventListener for tizenhwkey
	document.addEventListener('tizenhwkey', function(e) {
		if(e.keyName == "back") {
			try {
				tizen.application.getCurrentApplication().exit();
			} catch (error) {
				console.error("getCurrentApplication(): " + error.message);
			}
		}
	});
};
// window.onload can work without <body onload="">
window.onload = init;
