// JavaScript Document

// Objects references
var raquet;
var hitbox;
var imgraquet;
var scoreboard;
var scoreplayer;
var gameboard;
var boardsection;
var logo;
var imglogo;
var ball;

var timeelapsed = false;
var timetimer = 0;

// Game status
var gamestarted = false;

// moveRaquet function status
var lastx = 0;
var lastdir = "dx";

// Rotate function status
var rotating = false;
var steps = 0;
var idintruota = 0;
var interval = 2;
var soglia = 0;

// Game options
var boardsection_visibility = "visible";
var hitbox_visibility = "hidden";
var divisore_delta = 3;
var divisore_score = 10;
var num_vite = 10;
var num_tocchi = 0;
var num_tocchi_max = 12;
var gravita = 0;

function BallInfo(elem, img) {
	this.idint = 0; // ID Timer
	this.intballdefault = 100;
	this.intball = this.intballdefault; // Timer interval (game speed)
	this.zdir = -1; // Ball Depth
	this.xdir = 0; // Ball X Direction
	this.ydir = 0; // Ball Y Direction
	this.wmin = 12; // Max depth image size (change zdir)
	this.wmax = 30; // Min depth image size (change zdir)
	this.div = elem; // Reference to Ball div
	this.img = img; // Reference to Ball img
	this.posx;
	this.posy;
}

function HitBox(top, right, bottom, left)
{
	this.top = top;
	this.right = right;
	this.bottom = bottom;
	this.left = left;
}

function gameIntro()
{
	gamestarted = false;
	raquet = document.getElementById("raquet");
	imgraquet = document.getElementById("imgraquet");
	scoreboard = document.getElementById("scoreboard");
	scoreplayer = document.getElementById("scoreplayer");
	gameboard = document.getElementById("gameboard");
	hitbox = document.getElementById("hitbox");
	boardsection = document.getElementById("boardsection");
	logo = document.getElementById("logo");
	imglogo = document.getElementById("imglogo");
	ball = new BallInfo(document.getElementById("ball"), document.getElementById("imgball"));
	
	disableButton('giocabt');
	disableButton('resetbt');
	
	// Graphical effects
	logo.style.left = gameboard.offsetParent.offsetLeft + gameboard.offsetLeft + gameboard.offsetWidth / 2 - imglogo.width / 2;
	logo.style.top = gameboard.offsetParent.offsetTop + gameboard.offsetTop + gameboard.offsetHeight / 2 - imglogo.height / 2;
	setOpacity(logo, 0);
	logo.style.display = "";
	logo.style.visibility = "visible";
	loaded = true;
	showLogo(1);
}

function resetBall()
{
	if(ball.idint!=0) clearInterval(ball.idint);
	ball.idint = 0;
	ball.intball = ball.intballdefault;
	ball.img.width = ball.wmax;
	ball.img.height = ball.wmax;
	ball.div.style.left = gameboard.offsetParent.offsetLeft + gameboard.offsetLeft + gameboard.offsetWidth / 2 - ball.img.width / 2;
	ball.posx = gameboard.offsetWidth / 2 - ball.img.width / 2;
	ball.div.style.top = gameboard.offsetParent.offsetTop + gameboard.offsetTop + gameboard.offsetHeight / 2 - ball.img.height / 2;
	ball.posy = gameboard.offsetHeight / 2 - ball.img.height / 2;
	ball.zdir = -1;
	ball.xdir = 0;
	ball.ydir = 0;
	ball.div.style.visibility = "hidden";
	raquet.style.visibility = "hidden";
}

function gamePrepare()
{
	gamestarted = false;
	// Disattiva la gravità
	gravita = 0;
	num_tocchi = 0;
	
	// Nasconde il paddle
	raquet.style.visibility = "hidden";
	
	// Azzera il punteggio
	scoreplayer.value = "0";
	
	// Ferma la palla e la posiziona al centro della stanza
	resetBall();
	ball.div.style.visibility = "hidden";
	
	// Riposizione la SectionBoard
	gbhb = getBoardSection();
	boardsection.style.left = gbhb.left + "px";
	boardsection.style.top = gbhb.top + "px";
	boardsection.style.width = (gbhb.right - gbhb.left) + "px";
	boardsection.style.height = (gbhb.bottom - gbhb.top) + "px";
	boardsection.style.visibility = "hidden";
	
	// Nasconde la HitBox della racchetta
	hitbox.style.visibility = "hidden";
	
	// Disabilita il pulsante per l'avvio del gioco
	enableButton('giocabt');
	disableButton('resetbt');
	
	// Imposta la semitrasparenza al PADDLE
	setOpacity(raquet, 35);
	
	// Imposta le num_vite vite
	var container = document.getElementById('lifes');
	while(container.hasChildNodes())
	{
		container.removeChild(container.lastChild);
	}
	var img;
	for(var i = 0; i < num_vite; i++)
	{
		img = document.createElement("img");
		img.src = "img/ball.gif";
		img.width = 16;
		img.height = 16;
		container.appendChild(img);
	}
}

function gameInit()
{
	disableButton('giocabt');
	if(logo.style.visibility == "visible")
		hideLogo(99);
	else
		gameStart();
}

function gameStart()
{
	logo.style.visibility = "hidden";
	ball.div.style.visibility = "visible";
	ball.idint = setInterval("moveBall()", ball.intball);
	enableButton('resetbt');
	gamestarted = true;
}

function moveBall()
{	
	// Correggo la direzione Y in base al valore della gravità
	ball.ydir += gravita;
	
	// Sposto la pallina in base al movimento lungo l'asse X
	ball.posx += ball.xdir;
	
	// Sposto la pallina in base al movimento lungo l'asse Y
	ball.posy += ball.ydir;
	
	// Ridimensiono la pallina in base alla profondità (sposto lungo Z)
	ball.img.width = ball.img.width + ball.zdir;
	ball.img.height = ball.img.height + ball.zdir;
	// Prelevo le posizioni delle possibili collisioni con le pareti.
	gbhb = getBoardSection(); // GameBoard HitBox
	boardsection.style.left = gbhb.left + "px";
	boardsection.style.top = gbhb.top + "px";
	boardsection.style.width = (gbhb.right - gbhb.left) + "px";
	boardsection.style.height = (gbhb.bottom - gbhb.top) + "px";
	boardsection.style.visibility = boardsection_visibility;
	
	// Sposto la pallina in base alla profondità
	ball.div.style.left = ((ball.posx * (gbhb.right - gbhb.left) / parseInt(gameboard.offsetWidth)) + gbhb.left) + "px";
	ball.div.style.top = ((ball.posy * (gbhb.bottom - gbhb.top) / parseInt(gameboard.offsetHeight)) + gbhb.top) + "px";
	
	// Controllo le collisioni con le pareti
	if(
		(
		 (ball.xdir > 0) &&
		 (parseInt(ball.div.style.left) + parseInt(ball.img.width) >= gbhb.right)
	    ) ||
		(
		 (ball.xdir < 0) &&
		 (parseInt(ball.div.style.left) <= gbhb.left)
		)
	) { ball.xdir = -ball.xdir; playSound('collisionelaterale'); }
	
	if(
		(
		 (ball.ydir > 0) &&
		 (parseInt(ball.div.style.top) + parseInt(ball.img.height) >= gbhb.bottom)
	    ) ||
		(
		 (ball.ydir < 0) &&
		 (parseInt(ball.div.style.top) <= gbhb.top)
		)
	) { ball.ydir = -ball.ydir; playSound('collisionelaterale'); }
	
	// Controllo le collisioni con la parete di fondo e con la racchetta (se presente)
	if(ball.zdir < 0 && ball.img.width <= ball.wmin)
	{
		ball.zdir = -ball.zdir;
		playSound('collisionefondo');
	}
	else if(ball.zdir > 0 && ball.img.width >= ball.wmax)
	{
		// Controllo la collisione con la HitBox della racchetta
		var hb = getHitBox();
		var l = parseInt(ball.div.style.left);
		var r = parseInt(ball.div.style.left) + ball.wmax;
		var t = parseInt(ball.div.style.top);
		var b = parseInt(ball.div.style.top) + ball.wmax;
		if(l >= hb.left && r <= hb.right && t >= hb.top && b <= hb.bottom)
		{
			playSound('collisionepaddle');
			var cxp = Math.floor((l + r) / 2);
			var cyp = Math.floor((t + b) / 2);
			var cxh = Math.floor((hb.left + hb.right) / 2);
			var cyh = Math.floor((hb.top + hb.bottom) / 2);
			var dx = -Math.floor((cxh - cxp) / divisore_delta);
			var dy = -Math.floor((cyh - cyp) / divisore_delta);

			// Il punteggio aumenta maggiormente se la palla arriva con velocità x e y più alte
			var addscore = Math.floor(Math.sqrt(Math.pow(ball.xdir, 2) + Math.pow(ball.ydir, 2)));
			
			// Modo differenziale
			/*
			ball.xdir += dx;
			ball.ydir += dy;
			*/
			// Modo non differenziale
			ball.xdir = dx;
			ball.ydir = dy;
			
			// Il punteggio viene aumentato ulteriormente se il giocatore prende la palla
			// verso l'esterno del paddle (poichè i successivi tocchi saranno più difficili)
			addscore += Math.floor(Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)));
			
			// Se le guide di profondità sono nascoste, e se la posizione non è centrale,
			// ricevi 5 punti extra
			addscore += (boardsection_visibility=="hidden" && addscore!=0)?5:0;
			
			if(addscore > 0)
			{
				num_tocchi++;
				if(num_tocchi >= num_tocchi_max)
				{
					// Extra vita
					num_tocchi = 0;
					var container = document.getElementById('lifes');
					var img = document.createElement("img");
					img.src = "img/ball.gif";
					img.width = 16;
					img.height = 16;
					container.appendChild(img);
				}
			}
			
			ball.zdir = -ball.zdir;
			scoreplayer.value = (parseInt(scoreplayer.value) + addscore + Math.ceil(gravita));
			var request_interval = ball.intballdefault - Math.floor(parseFloat(scoreplayer.value) / divisore_score);
			if(request_interval != ball.intball)
			{
				clearInterval(ball.idint);
				request_interval = request_interval<=0?1:request_interval;
				ball.intball = request_interval;
				ball.idint = setInterval("moveBall()", ball.intball);
			}
			if(parseInt(scoreplayer.value) >= 100 * divisore_score)
			{
				clearInterval(ball.idint);
				ball.idint = 0;
				playSound('vittoria');
				disableButton('resetbt');
				alert("Hai raggiunto il livello massimo con " + (scoreplayer.value) + " punti! Hai vinto! Congratulazioni!");
				resetBall();
				gameIntro();
			}
		}
		else
		{
			scoreplayer.value = (parseInt(scoreplayer.value) - 5);
			var container = document.getElementById('lifes');
			if(!container.hasChildNodes())
			{
				clearInterval(ball.idint);
				ball.idint = 0;
				playSound('sconfitta');
				disableButton('resetbt');
				alert("Non hai più palline a disposizione, hai perso! Il tuo punteggio è " + (scoreplayer.value));
				resetBall();
				gameIntro();
			}
			else
			{
				playSound('pallapersa');
				num_tocchi = Math.ceil(num_tocchi / 2);
				container.removeChild(container.lastChild);
				resetBall();
				gameStart();
			}
		}
	}
}

function moveRaquet(ev)
{
	if(gamestarted)
	{		
		if (!ev) var ev = window.event;
		var posx = 0;
		var posy = 0;
		if (ev.pageX || ev.pageY)
		{
			posx = ev.pageX;
			posy = ev.pageY;
		}
		else if (ev.clientX || ev.clientY)
		{
			posx = ev.clientX + document.body.scrollLeft;
			posy = ev.clientY + document.body.scrollTop;
		}
		if((posx - lastx > soglia) && !rotating)
		{
			if(lastdir != "dx") ruota("dx");
			lastdir = "dx";
		}
		else if((posx - lastx < -soglia) && !rotating)
		{
			if(lastdir != "sx") ruota("sx");
			lastdir = "sx";
		}
		lastx = posx;
		marginelaterale = imgraquet.height / 4;
		
		if(posx <= gameboard.offsetParent.offsetLeft + gameboard.offsetLeft + gameboard.offsetWidth + marginelaterale)
		{
			if(posx >= gameboard.offsetParent.offsetLeft + gameboard.offsetLeft - marginelaterale)
				raquet.style.left = (posx - imgraquet.width / 2) + "px";
			else
				raquet.style.left = (gameboard.offsetParent.offsetLeft + gameboard.offsetLeft - marginelaterale - imgraquet.width / 2) + "px";
		}
		else
			raquet.style.left = (gameboard.offsetParent.offsetLeft + gameboard.offsetLeft + gameboard.offsetWidth - imgraquet.width / 2 + marginelaterale) + "px";
		if(posy <= gameboard.offsetParent.offsetTop + gameboard.offsetTop + gameboard.offsetHeight + marginelaterale)
			raquet.style.top = (posy - imgraquet.height / 2) + "px";
		else
			raquet.style.top = (gameboard.offsetParent.offsetTop + gameboard.offsetTop + gameboard.offsetHeight - imgraquet.height / 2 + marginelaterale) + "px";

		raquet.style.visibility = "visible";
		hb = getHitBox();
		hitbox.style.left = hb.left + "px";
		hitbox.style.top = hb.top + "px";
		hitbox.style.width = (hb.right - hb.left) + "px";
		hitbox.style.height = (hb.bottom - hb.top) + "px";
		hitbox.style.visibility = hitbox_visibility;
	}
}

function ruota(dir)
{
	// Uso un nuovo paddle, non serve più ruotare la racchetta
	//rotating = true;
	//steps = 10;
	//idintruota = setInterval("sizeDown(\"" + dir + "\")", interval);
}

function sizeUp()
{
	imgraquet.width = parseInt(imgraquet.width) + 8;
	raquet.style.left = (parseInt(raquet.style.left) - 4) + "px";
	steps--;
	if(steps==0)
	{
		clearInterval(idintruota);
		idintruota = 0;
		rotating = false;
	}
}

function sizeDown(dir)
{
	imgraquet.width = parseInt(imgraquet.width) - 8;
	raquet.style.left = (parseInt(raquet.style.left) + 4) + "px";
	steps--;
	if(steps==0)
	{
		imgraquet.src = "img/raquet" + dir + ".gif";
		clearInterval(idintruota);
		idintruota = 0;
		steps = 10;
		idintruota = setInterval("sizeUp()", interval);
	}
}

function getHitBox()
{
	var top;
	var bottom;
	var right;
	var left;
	top = parseInt(raquet.style.top);
	/* Uso un nuovo paddle
	bottom = parseInt(raquet.style.top) + 50;
	if(lastdir == "dx")
	{
		left = parseInt(raquet.style.left) + 30;
		right = parseInt(raquet.style.left) + 80;
	}
	else
	{
		left = parseInt(raquet.style.left);
		right = parseInt(raquet.style.left) + 50;
	}*/
	left = parseInt(raquet.style.left);
	right = left + imgraquet.width;
	bottom = top + imgraquet.height;
	var margin = Math.floor(ball.wmax * 2 / 3);
	return new HitBox(top - margin, right + margin, bottom + margin, left - margin);
}

function getBoardSection()
{
	var top;
	var bottom;
	var right;
	var left;
	var wsec = (gameboard.offsetWidth * ball.img.width) / ball.wmax;
	var hsec = (gameboard.offsetHeight * wsec) / gameboard.offsetWidth;
	top = gameboard.offsetParent.offsetTop + gameboard.offsetTop + (gameboard.offsetHeight - hsec) / 2;
	left = gameboard.offsetParent.offsetLeft + gameboard.offsetLeft + (gameboard.offsetWidth - wsec) / 2;
	right = left + wsec;
	bottom = top + hsec;
	return new HitBox(top, right, bottom, left);
}

function setOpacity(obj, opacity){
	// IE/Win
	if(navigator.appName == "Microsoft Internet Explorer")
		obj.style.filter = "alpha(opacity:"+opacity+")";
	// Mozilla
	if (navigator.appName == "Netscape")
		obj.style.opacity = opacity / 100;
}

function waitTime(ms, strcallback)
{
	timeelapsed = false;
	if(timetimer != 0) clearTimeout(timetimer);
	timetimer = setTimeout("wakeUp(\"" + strcallback + "\")", ms);
}

function wakeUp(strcallback)
{
	if(timetimer != 0) clearTimeout(timetimer);
	timetimer = 0;
	timeelapsed = true;
	eval(strcallback);
}

function showLogo(opacity)
{
	setOpacity(logo, opacity);
	if(opacity==100) { gamePrepare(); return; }
	waitTime(3, "showLogo(" + (opacity + 1) + ")");
}

function hideLogo(opacity)
{
	setOpacity(logo, opacity);
	if(opacity==0)
	{
		gameStart();
		return;
	}
	waitTime(3, "hideLogo(" + (opacity - 1) + ")");
}

function guide(vis)
{
	boardsection_visibility = vis;
}

function gravity(g)
{
	gravita += g;
}

function enableButton(bt)
{
	if(navigator.appName == "Microsoft Internet Explorer")
		document.getElementById(bt).disabled = false;
	// Mozilla
	if (navigator.appName == "Netscape")	
		document.getElementById(bt).removeAttribute("disabled");
}
function disableButton(bt)
{
	if(navigator.appName == "Microsoft Internet Explorer")
		document.getElementById(bt).disabled = true;
	if (navigator.appName == "Netscape")
		document.getElementById(bt).setAttribute("disabled", "");
}

function playSound(soundname) {
 var sound = document.getElementById(soundname);
 if(!sound) { /*document.title += soundname + "; ";*/ return; }
 // make an effort to stop and rewind any playback
 // already in progress so that the sound starts over.
 // Otherwise this call has no effect when the sound
 // is already in progress. You can remove these lines
 // if you don't like this behavior.
 try {
  sound.Stop();
  sound.Rewind();
 } catch (e) { /* A player that doesn't support Stop and Rewind */ }

 try {
  // For RealPlayer-enabled browsers.
  // Some versions of RealPlayer do not
  // offer a Play() function and will
  // fail to play sound if we try to
  // call Play().
  sound.DoPlay();
 } catch (e) {
  // If DoPlay doesn't work, call Play.
  // This works for all other audio
  // plug-ins.
  	try { sound.Play(); }
	catch (e)
	{
		try { sound.play(); } catch (e) {}
	}
 }
}