var txtLevel;
var pc;
var drE;
const PC_IDLE = 5;
const PC_JUMP = 0;

var leftArrowDown = false;
var rightArrowDown = false;
var upArrowDown = false;

var gameTimer;

const GRAVITY = 1;
var fallSpeed = 0;

var platforms = new Array();
var spikeyGuys = new Array();

var level = 0;	// game will begin one level higher than this

var lifebar;
var numLives = 0;

var sndMusic = new Audio();
var sndJump = new Audio();

function init(){
	lifebar = document.getElementById('lifebar');
	for(var i=0; i<3; i++) addLife();

	pc = document.getElementById('pc');
	pc.style.width = '72px';
	pc.style.height = '81px';
	pc.JUMP_FORCE = 18;
	pc.SPEED = 5;

	drE = document.getElementById('drE');
	drE.style.width = '44px';
	drE.style.height = '140px';

	sndMusic.loop = true;
	sndJump.src = 'audio/jump.mp3';

	txtLevel = document.getElementById('txtLevel');

	nextLevel();
}

function nextLevel(){
	document.getElementById('btnContinue').style.display = 'none';
	level++;

	fallSpeed = 0;
	leftArrowDown = false;
	rightArrowDown = false;
	upArrowDown = false;

	pc.style.left = '190px';
	pc.style.top = '50px';
	pc.frame = PC_IDLE;
	pc.inAir = false;

	for(var i=0; i<platforms.length; i++){
		gameWindow.removeChild(platforms[i]);
	}
	platforms = new Array();

	for(var i=0; i<spikeyGuys.length; i++){
		gameWindow.removeChild(spikeyGuys[i]);
	}
	spikeyGuys = new Array();

	txtLevel.innerHTML = 'LEVEL ' + level;

	if(level==1){
		drE.style.left = '1600px';
		drE.style.top = '250px';

		addPlatform(0, 380, 500, 20);
		addPlatform(150, 240, 100, 20);
		addPlatform(640, 380, 300, 20);
		addPlatform(400, 300, 100, 100);
		addPlatform(900, 180, 100, 20);
		addPlatform(750, 270, 100, 20);
		addPlatform(1180, 380, 1000, 20);

		addSpikeyGuy(1300, 322);

		sndMusic.src = 'audio/level_1_music.mp3';
		sndMusic.volume = 0.2;
		sndMusic.currentTime = 0;
		sndMusic.play();
	}
	else if(level==2){
		drE.style.left = '500px';
		drE.style.top = '250px';

		addPlatform(0, 380, 250, 20);
		addPlatform(350, 380, 250, 20);
	}
	else if(level==3){
		drE.style.left = '650px';
		drE.style.top = '150px';

		addPlatform(0, 380, 500, 20);
		addPlatform(550, 280, 150, 20);
	}

	gameTimer = setInterval(gameloop, 50);
}

function addLife(){
	numLives++;
	var life = document.createElement('IMG');
	life.src='images/heart.png';
	lifebar.appendChild(life);
}

function removeLife(){
	if(numLives>0){
		numLives--;
		lifebar.removeChild(lifebar.lastChild);
	}
	else{
		gameWindow.innerHTML = '<br><br>You lose!';
		gameWindow.className = 'msgGameOver';
	}
}

function addPlatform(x, y, w, h){
	var p = document.createElement('DIV');
	p.className = 'platform';
	p.style.left = x + 'px';
	p.style.top = y + 'px';
	p.style.width = w + 'px';
	p.style.height = h + 'px';

	platforms.push(p);
	gameWindow.appendChild(p);
}

function addSpikeyGuy(x, y){
	var spikey = document.createElement('IMG');
	spikey.className = 'spikey';
	spikey.src = "images/spikey.png";
	spikey.style.left = x + 'px';
	spikey.style.top = y + 'px';
	spikey.style.width = '50px';
	spikey.style.height = '58px';

	spikeyGuys.push(spikey);
	gameWindow.appendChild(spikey);
}

function gameloop(){
	// HORIZONTAL MOVEMENT
	if(leftArrowDown){
		pc.className = "flipHorizontal";
		pc.style.left = parseInt(pc.style.left) - pc.SPEED + 'px';
		var sideHit = false;
		for(var i=0; i<platforms.length; i++){
			if( hittest(pc, platforms[i]) ) sideHit = true;
		}
		pc.style.left = parseInt(pc.style.left) + pc.SPEED + 'px';

		if( ! sideHit ){
			for(var i=0; i<platforms.length; i++){
				platforms[i].style.left = parseInt(platforms[i].style.left) + pc.SPEED + 'px';
			}
			for(var i=0; i<spikeyGuys.length; i++){
				spikeyGuys[i].style.left = parseInt(spikeyGuys[i].style.left) + pc.SPEED + 'px';
			}
			drE.style.left = parseInt(drE.style.left) + pc.SPEED + 'px';
			
			if(! pc.inAir) pc.frame++;
		}
	}
	if(rightArrowDown){
		pc.className = "";
		pc.style.left = parseInt(pc.style.left) + pc.SPEED + 'px';
		var sideHit = false;
		for(var i=0; i<platforms.length; i++){
			if( hittest(pc, platforms[i]) ) sideHit = true;
		}
		pc.style.left = parseInt(pc.style.left) - pc.SPEED + 'px';

		if( ! sideHit ){
			for(var i=0; i<platforms.length; i++){
				platforms[i].style.left = parseInt(platforms[i].style.left) - pc.SPEED + 'px';
			}
			for(var i=0; i<spikeyGuys.length; i++){
				spikeyGuys[i].style.left = parseInt(spikeyGuys[i].style.left) - pc.SPEED + 'px';
			}
			drE.style.left = parseInt(drE.style.left) - pc.SPEED + 'px';

			if(! pc.inAir) pc.frame++;
		}
	}

	// VERTICAL MOVEMENT
	fallSpeed += GRAVITY;
	pc.style.top = parseInt(pc.style.top) + fallSpeed + 'px';

	for(var i=0; i<platforms.length; i++){
		if( hittest(pc, platforms[i]) ){
			if(fallSpeed<0){
				// hit bottom of platform
				pc.style.top = parseInt(platforms[i].style.top) + parseInt(platforms[i].style.height) + 'px';
				fallSpeed *= -1;
			}
			else{
				// hit top of platform
				pc.style.top = parseInt(platforms[i].style.top) - parseInt(pc.style.height) + 'px';

				if(upArrowDown){
					fallSpeed = -1 * pc.JUMP_FORCE;
					sndJump.currentTime = 0;
					sndJump.play();
				}
				else{
					if(pc.inAir){
						pc.inAir = false;
						pc.frame = PC_IDLE;
					}
					fallSpeed = 0;				
				}
			}
		}
	}

	pc.style.backgroundPositionX = pc.frame * 72 + "px";

	// CHECK FOR COLLISSION WITH A SPIKEYGUY
	for(var i=0; i<spikeyGuys.length; i++){
		if(radialHittest(pc, spikeyGuys[i])){
			die('So sad... Spikey Guy got you.');
		}
	}

	// CHECK FOR COLLISSION WITH drE
	if( hittest(pc, drE) ){
		clearInterval(gameTimer);
		sndMusic.pause();

		alert('You saved Dr. Enfield!');
		if(level==3){
			gameWindow.innerHTML = '<br><br>You win!';
			gameWindow.className = 'msgGameOver';
		}
		else{
			document.getElementById('btnContinue').style.display = 'block';
		}
	}
	
	// CHECK FOR FALLING IN HOLE
	if( parseInt(pc.style.top) > 400 ){
		die('So sad... You fell in a hole.');
	}
}

function die(msg){
	clearInterval(gameTimer);
	sndMusic.pause();

	alert(msg);

	removeLife();
	level--;
	nextLevel();
}

document.addEventListener('keydown', function(event){
	if(event.keyCode==37 || event.keyCode==65) leftArrowDown = true;
	if(event.keyCode==39 || event.keyCode==68) rightArrowDown = true;
	if(event.keyCode==38 || event.keyCode==87){
		upArrowDown = true;
		pc.inAir = true;
		pc.frame = PC_JUMP;
	}
});

document.addEventListener('keyup', function(event){
	if(event.keyCode==37 || event.keyCode==65) leftArrowDown = false;
	if(event.keyCode==39 || event.keyCode==68) rightArrowDown = false;
	if(event.keyCode==38 || event.keyCode==87) upArrowDown = false;
});

function hittest(a, b){
	var aX1 = parseInt(a.style.left);
	var aY1 = parseInt(a.style.top);
	var aX2 = aX1 + parseInt(a.style.width)-1;
	var aY2 = aY1;
	var aX3 = aX1;
	var aY3 = aY1 + parseInt(a.style.height)-1;
	var aX4 = aX2;
	var aY4 = aY3;

	var bX1 = parseInt(b.style.left);
	var bY1 = parseInt(b.style.top);
	var bX2 = bX1 + parseInt(b.style.width)-1;
	var bY2 = bY1;
	var bX3 = bX1;
	var bY3 = bY1 + parseInt(b.style.height)-1;
	var bX4 = bX2;
	var bY4 = bY3;

	var hOverlap = true;
	if(aX1<bX1 && aX2<bX1) hOverlap = false;
	if(aX1>bX2 && aX2>bX2) hOverlap = false;

	var vOverlap = true;
	if(aY1<bY1 && aY3<bY1) vOverlap = false;
	if(aY1>bY3 && aY3>bY3) vOverlap = false;

	if(hOverlap && vOverlap) return true;
	else return false;
}

// radial hittest is based on distance between the midpoints of two objects
function radialHittest(a, b){
	var aW = parseInt(a.style.width);
	var aH = parseInt(a.style.height);
	// get center point of object a
	var aX = parseInt(a.style.left) + aW/2;
	var aY = parseInt(a.style.top) + aH/2;
	// get radius of object a (average of height and width / 2)
	var aR = (aW + aH) / 4;

	var bW = parseInt(b.style.width);
	var bH = parseInt(b.style.height);
	// get center point of object b
	var bX = parseInt(b.style.left) + bW/2;
	var bY = parseInt(b.style.top) + bH/2;
	// get radius of object b (average of height and width / 2)
	var bR = (bW + bH) / 4;

	var minDistance = aR + bR;

	var cXs = (aX - bX) * (aX - bX); // change in X squared
	var cYs = (aY - bY) * (aY - bY); // change in Y squared
	var distance = Math.sqrt(cXs + cYs);

	if(distance < minDistance) return true;
	else return false;
}
