/*
 * trajectory.js
 * Builds on the example in arrow.js. This example shows how to
 * calculate and draw the trajectory path of the arrow.
 */
  
var tmp = null;

// Reference to canvas context
var ctx = false;

// Update frequency
var fHz = 1000/60;

// Canvas size
var canvas_size = {x: 10, y: 10};

// List of on-going explosions
var entities = [];

// Reference to the interval, used to
// clear it at reset.
var interval = null;

// Box2D World
var world = null;

// Pixel-to-Meter ratio
var PTM_RATIO = 30.0;

var initialised = false;


var move = false;
var angle = null;
var angle_degrees = null;
var hero = document.getElementById("playerSprite");
var fireRing = document.getElementById("fireRing");
var end_simulation = false;
var show_response = false;
var frame_index = 0;
var tick = 5;
var pointMarker=0;
var tryNumber = 0;

var jumpSound =document.getElementById('jump');
var winSound =document.getElementById('win');
var loseSound =document.getElementById('game-over');

/*
 * createMap
 * Draws the static and dynamic bodies used.
 */
function createMap(){
	// Wall thickness
	var wt = 25;
	// Platform thickness
	var pt = 10;
	// Platform width
	var pw = 40;

	// Left wall
	tmp = createBox(p2b(wt), 
			  p2b(canvas_size.y/2), 
			  p2b(wt), 
			  p2b(canvas_size.y/2), 
			  b2Body.b2_staticBody);
	tmp.SetUserData("Left wall");
			  
	// Right wall
	tmp = createBox(p2b(wt), 
			  p2b(canvas_size.y/2), 
			  p2b(canvas_size.x - wt), 
			  p2b(canvas_size.y/2), 
			  b2Body.b2_staticBody);
	tmp.SetUserData("Right wall");
			  
	// Ground
	tmp = createBox(p2b(canvas_size.x / 2), 
			  p2b(wt), 
			  p2b(canvas_size.x / 2), 
			  p2b(canvas_size.y - wt), 
			  b2Body.b2_staticBody);
	tmp.SetUserData("Ground");
	
	// Ceiling
	tmp = createBox(p2b(canvas_size.x / 2), 
			  p2b(wt), 
			  p2b(canvas_size.x / 2), 
			  p2b(wt), 
			  b2Body.b2_staticBody);
			  
	tmp.SetUserData("Ceiling");

}

/*
 * getTrajectoryPoint
 * This functions returns the coordinates of step n 
 * in a trajectory based on the starting position and
 * starting velocity.
 */
function getTrajectoryPoint( startingPosition, startingVelocity, n ){
	var sP = new b2Vec2(startingPosition.x, startingPosition.y);
	var sV = new b2Vec2(startingVelocity.x, startingVelocity.y);
	var t = 1 / 30.0;  // seconds per time step (at 60 fps)


	sV.Multiply(t); // m/s
	sV.Multiply(n);

	var gravity = new b2Vec2(world.GetGravity().x, world.GetGravity().y);
	
	gravity.Multiply(t*t); // m/s/s
	
	gravity.Multiply((Math.pow(n,2) + n) * 0.5);
	
	sV.Add(gravity);
	
	sP.Add(sV);
	
	// Return the coordinates of the trajectory point.
	return new b2Vec2(sP.x, sP.y);
}


/*
 * preventDefault
 * Used to prevent the default behavior of
 * double clicks and select start events.
 */
function preventDefault(event){
	if (event.preventDefault)
		event.preventDefault();
	else
		event.returnValue= false;
	return false;
}

/*
 * reset
 * Resets the demo.
 */
function reset() {
	clean_try();
	move = false;
	angle =  null;
	end_simulation = false;
	show_response = false;
	ctx.clearRect(0, 0, canvas_size.x, canvas_size.y);
	world = null;
	entities = [];
	deferred_kills = [];
	window.clearInterval(interval);
	interval = null;
	initialised = false;
	pointMarker=0;
	document.getElementById('angle').value = "";
	document.getElementById('ganaste').style.display = 'none';
	document.getElementById('perdiste').style.display = 'none';  
	init();
}


/*
 * removeEntity
 * Remove an entity object from the entity list.
 */
function removeEntity(entity) {
	world.DestroyBody(entity.physBody);
	return entities.erase(entity);
}

/*
 * update
 * The main update function
 */
function update(){

	var deferred_kills = [];
	// Update the world simulation
	world.Step(
		  1/60,      //frame-rate
		  10,       //velocity iterations
		  10       //position iterations
	);

	// First update all entities
	for ( var i = 0; i < entities.length; i++ ) {
		entities[i].update();
		
		if(entities[i]._killed)
			deferred_kills.push(entities[i]);
	}
	
	// Remove any entities that are dead
	for ( var i = 0; i < deferred_kills.length; i++ ) {
		removeEntity(deferred_kills[i]);
	}

	var startPos = new b2Vec2(150, 290);	
  	// Draw debug data on the canvas
	world.DrawDebugData();
	ctx.save();
	ctx.drawImage(fireRing,frame_index*180,0,180,320,220,0,180,320);
	if(frame_index<10){
		tick--;
		if(tick == 0){ 
			frame_index++;
			tick = 5;
		}
	}else if(frame_index == 10){
		frame_index = 0;
	}
	if ( angle ) {
		// Hard coded staring position on the canvas.
		// In a game, this would be the position of the
		// player.

		var startPositionMeters = startPos.Copy();

		startPositionMeters.Multiply(1/PTM_RATIO);
		
		// Vector value of velocity based on force and
		// trajectory angle.
		var startingVelocity =  new b2Vec2(10.75 * Math.cos(angle),
                                      -1 * 10.75 * Math.sin(angle));
		// Starting position when calculating the trajectory
		// position at a given step
		var trajectoryStartingPos = new b2Vec2(0,0);

		// Determines the number of trajectory points to calculate.
		var numTrajectoryPoints = 180;

		// Set the canvas context drawing parameters
		// for the trajectory markers. 
		ctx.save();
		ctx.fillStyle = 'green';
		ctx.lineWidth = 0.1;
		ctx.strokeStyle = '#003300';


		// Size of the trajectory marker
		var radius = 2;

		// Initialise the starting position of the ray.
		// This value will be set to the value of the end
		// of the ray at the end of every loop.

		var show_trajectory=true;

		for (i=0;i<=pointMarker;i++) {

			if ( !show_trajectory ){
				end_simulation = true;
				ctx.drawImage(hero,trajectoryMarkerPos.x-22,trajectoryMarkerPos.y-35); 
				break;
			};

			var startOfRay = startPositionMeters.Copy();

			// Flag indicating whether to draw the trajectory.
			// Set to false when the raycast hits a physics body
			// to prevent the trajectory from passing through
			// objects.
			var show_trajectory = true;

			// Loop to determine the trajectory points
			
			// Stop drawing trajectory markers.

			// Current trajectory coordinates for step i.
			var cur_pos = getTrajectoryPoint(startPositionMeters,
											 startingVelocity, 
											 i);

			// Calculate the coordinates of the trajectory marker
			// on the canvas.
			var trajectoryMarkerPos = cur_pos.Copy();
			trajectoryMarkerPos.Multiply(PTM_RATIO);

			// The end of the ray is the current position in the
			// trajectory. The ray will therefore be the line 
			// from the previous trajectory position to the current
			// trajectory position.
			var endOfRay = cur_pos.Copy();

			// Cast the ray to see if it hits some physics body. If it
			// does then set show_trajectory to false and change the fill
			// style to indicate the expected collision point.
			world.RayCast(function(raycast){
								   var b = raycast.GetBody();
								   var stop = false;
								   if(b){
									  ctx.fillStyle = 'red';
									  radius = 2;
									  show_trajectory = false;
								   }
							   }, startOfRay, endOfRay);


			// Draw the trajectory marker
			if(i == pointMarker){ 
				ctx.drawImage(hero,trajectoryMarkerPos.x-22,trajectoryMarkerPos.y-35); 
			}  
			ctx.beginPath();
			ctx.arc(trajectoryMarkerPos.x, 
				    trajectoryMarkerPos.y, 
				    radius, 
				    0, 
				    2 * Math.PI, 
				    false);
			ctx.fill();
			ctx.stroke();
			startOfRay = endOfRay;

		}

		pointMarker++;
	} else {
			ctx.save();	
			ctx.drawImage(hero,startPos.x-22,startPos.y-17); 		
	}

	ctx.restore();

	if(end_simulation){
		alert_result();
	}

 	//golfPlayer.update();
	world.ClearForces();
}


/*
 * 
 *
 */
function alert_result(){
	if(angle_degrees == 30){
		clean_try();
		document.getElementById('perdiste').style.display = 'none';  
		document.getElementById('ganaste').style.display = 'block'; 
		if(winSound) { winSound.play(); }
		winSound = null;
		tryNumber = 0;
	}else{ 
		document.getElementById('perdiste').style.display = 'block';
		document.getElementById('ganaste').style.display = 'none';  
		if(loseSound) { loseSound.play(); }
		loseSound = null;
		if(tryNumber>0){alert_try();}
	}
}

/*
 * 
 *
 */
function alert_try(){
	if(tryNumber == 1){
		document.getElementById('intento1').style.display = 'block';  
	}else if(tryNumber > 1){
		document.getElementById('intento1').style.display = 'none';  
		document.getElementById('intento2').style.display = 'block';
	}
}

/*
 * 
 *
 */
function clean_try(){
	document.getElementById('intento1').style.display = 'none';  
	document.getElementById('intento2').style.display = 'none';
}

/*
 * init
 * Initialises the demo.
 */
function init(){	
	//
	// Create the box2d world
	//

	
	world = new b2World(
						new b2Vec2(0, 10),   //gravity
						true                 //allow sleep
					   );
	
	//
	// Configure debug draw
	//
	setDebugDraw(world);
	
	var canvas = document.getElementById('canvas');
				
	ctx = canvas.getContext('2d');
	
	canvas_size.x = canvas.width;
	canvas_size.y = canvas.height;
	
	if ( !initialised ) {
		var start = document.getElementById('start_btn');
		start.addEventListener('click', function(e) {
			tryNumber++;
			// The mouse position of the event
			angle_degrees = parseFloat(document.getElementById('angle').value);
		  angle = Math.radians(angle_degrees);
			if( angle_degrees != "" ){       		    
				// Calculate trajectory angle	

				pointMarker=0;

				end_simulation=false;

				document.getElementById('ganaste').style.display = 'none';
				document.getElementById('perdiste').style.display = 'none';  
				
				move = true;
				jump.play();
				winSound =document.getElementById('win');
				loseSound =document.getElementById('game-over');
			}
		}, false);
		
		// Create event listeners
		canvas.addEventListener('selectstart', 
								function(e){preventDefault(e);}, 
								false);
		canvas.addEventListener('dblclick', 
								function(e){preventDefault(e);}, 
								false);
		
		// The reset button.
		var reset_btn = document.getElementById('reset_btn');
		reset_btn.addEventListener('click', 
								function(e) { reset(); }, 
								false);
		
		// Set the first time the init function is called.
		initialised = true;
	}
	
	
	createMap();
	interval = window.setInterval(update, fHz);
}

