var ticker;
var gameSpeed=10;
var watchSet=new Array();
var isout=false;
var lastKey=0;

// config
var config={
	animSpeed:800,
	polish:true,
	maxScore:11
};

// table properties
var table={
	width:800,
	height:600,
	borderWidth:5,
	serviceNumber:0,
	activePlayer:1
}

// paddle properties
var paddle={
	mass:1,
	maxAccel:10,
	accelFactor:2,
	width:15,
	height:80
}

var ball={
	size:10,
	mass:0.5,
	moving:true,
	maxAccel:7
}

var players=[0,1];

$(document).ready(function() {
	$(document).keydown(function(event) {
		lastKey=event.keyCode;
		switch (event.keyCode) {
			case 87:players[0].movingUp=true;break;
			case 83:players[0].movingDown=true;break;
			case 38:players[1].movingUp=true;break;
			case 40:players[1].movingDown=true;break;
			default:
		}
	}).keyup(function(event) {

		switch (event.keyCode) {
			case 87:players[0].movingUp=false;break;
			case 83:players[0].movingDown=false;break;
			case 38:players[1].movingUp=false;break;
			case 40:players[1].movingDown=false;break;
			case 32:
				if (!ball.moving) launchBall();
				if (table.activePlayer<0) newGame();
			break;
			default:
		}

	});

	buildTable();
	addWatch('accel0','players[0].accel');
	addWatch('movingUp0','players[0].movingUp');
	addWatch('moveDown0','players[0].movingDown');
	addWatch('paddleY',"$('#paddle0').offset().top");
	addWatch('bx',"$('.ball').offset().left-$('#table').offset().left");
	addWatch('isout',"isout");
	addWatch('lastKey',"lastKey");
	addWatch('serviceNumber','table.serviceNumber');
	addWatch('activePlayer','table.activePlayer');
	addWatch('ball.moving','ball.moving');
	ticker=setTimeout(tick,gameSpeed);
});

function buildTable(callback) {
	$('<div id="table"></div>').appendTo($('#wrapper')).css({width:table.width,height:table.height,marginTop:-table.height/2,marginLeft:-table.width/2})
		.css({'border-width':table.borderWidth+'px 0 '+table.borderWidth+'px 0'}).fadeIn(config.animSpeed*2);
	table.y=$('#table').offset().top+table.borderWidth;
	table.x=$('#table').offset().left;

	$('<div id="sound"></div>').appendTo($('#table')).sound({swf: 'sound/Player.swf'});

	$('<div id="net"></div>').appendTo($('#table')).css({height:table.height,borderRightWidth:table.borderWidth,marginLeft:-table.borderWidth/2});
	for (i=0;i<players.length;i++) {
		players[i]={
			score:0,
			accel:0,
			movingUp:false,
			movingDown:false
		};

		$('<div class="score" id="score'+i+'">'+players[i].score+'</div>').appendTo($('#table'));
	}

	newService();
}

function newService() {
	table.serviceNumber++;
	isout=false;
	ball.velocityX=0;
	ball.velocityY=0;

	$('.paddle').add($('<div class="Del"></div>').appendTo($('#wrapper')).css('display','block')).queue(function() {$(this).fadeOut(config.animSpeed);$(this).dequeue();}).eq(0).queue(function() {
		$('.paddle,.Del').remove();

		for (i=0;i<players.length;i++) {
			$('<div class="paddle"></div>').attr('id','paddle'+i).css({width:paddle.width,height:paddle.height,top:(table.height-paddle.height)/2}).appendTo($('#table')).addClass(config.polish?'rounded':'');
		}
		$('.paddle').fadeIn(config.animSpeed);

		ball.moving=false;
		table.activePlayer=(table.serviceNumber%2==0?table.activePlayer:Math.abs(table.activePlayer-1));
		$('<div class="ball"></div>').appendTo($('#table'))
			.css({width:ball.size,height:ball.size,top:(table.height-ball.size)/2,left:table.activePlayer==1?table.width-paddle.width-ball.size:paddle.width})
			.addClass(config.polish?'rounded':'').fadeIn(config.animSpeed,function() {

		});

	});

}

function launchBall() {
	a=rnd(Math.round(ball.maxAccel/4),ball.maxAccel);
	b=(rnd(0,1)?1:-1)*(ball.maxAccel-Math.abs(a));
	window.status=a+'x'+b;
	ball.velocityX=(table.activePlayer==1?-1:1)*a;
	ball.velocityY=b;
	ball.moving=true;
}

function refreshDebug() {
	out='';
	for (i in watchSet) out+=watchSet[i].label+'='+eval(watchSet[i].expression)+'<br/>';
	$('#debug').html(out);
}

function addWatch(label,expression) {
	watchSet[watchSet.length]={label:label,expression:expression};
}

function tick() {
//	refreshDebug();
	for (i=0;i<players.length;i++) {
		if (players[i].movingUp || players[i].movingDown || players[i].accel!=0) {
			players[i].accel+=((players[i].movingUp?-1:0)+(players[i].movingDown?1:0))*paddle.accelFactor;
			if (Math.abs(players[i].accel)>paddle.maxAccel) players[i].accel=(players[i].accel<0?-1:1)*paddle.maxAccel;
			$('#paddle'+i).data('accel',players[i].accel);
			if (players[i].accel!=0) {
				movePaddleBy(i,players[i].accel);
				players[i].accel+=(players[i].accel<0?1:-1)*paddle.mass;
			}
		}
		if (!ball.moving && i==table.activePlayer) $('.ball').css('top',$('#paddle'+table.activePlayer).offset().top-table.y+(paddle.height-ball.size)/2+'px');
	}


	$('.ball').each(function() {
		bx=$(this).offset().left;
		by=$(this).offset().top;

		newx=bx-table.x+ball.velocityX;
		newy=by-table.y+ball.velocityY;
		lb=table.height-ball.size;
		if (newy>lb || newy<0) {
			ball.velocityY=-ball.velocityY;
		}


		if (!isout) {
			if (ball.moving) checkCollision($(this),$('.paddle'));

			function out() {
				$('.ball').fadeOut(config.animSpeed,function() {
					gameOver=false;
					for (i=0;i<players.length;i++) if (players[i].score==config.maxScore) {gameOver=true;endGame(i+1);}
					if (!gameOver) {
						newService();
						out=false;
						$(this).remove();
					}
				});
			}

			if (bx-$('#table').offset().left<=0) {players[1].score++;updateScore();out();isout=true;}
			if (bx-$('#table').offset().left>=table.width) {players[0].score++;updateScore();out();isout=true;}

		}

		$(this).css({left:newx,top:newy});
	});

	ticker=setTimeout(tick,gameSpeed);
}

function movePaddleBy(id,y) {
	var py=$('#paddle'+id).offset().top;
	var newy=py-table.y+y;
	if (newy<0) {
		newy=0;
		players[id].accel=-players[id].accel;
	}
	if (newy>table.height-paddle.height) {
		newy=table.height-paddle.height;players[id].accel=-players[id].accel;
	}
	$('#paddle'+id).css('top',newy+'px');
}

function checkCollision(object,obstacles,callback) {
	var ax=$(object).offset().left+ball.velocityX;
	var ay=$(object).offset().top+ball.velocityY;
	var aw=$(object).width();
	var ah=$(object).height();

	$(obstacles).each(function() {
		var hTop=false;
		var hBottom=false;
		var hLeft=false;
		var hRight=false

		var bx=$(this).offset().left;
		var by=$(this).offset().top;
		var bw=$(this).width();
		var bh=$(this).height();

		if (
			(ax>=bx && ax<=bx+bw && ay>=by && ay<=by+bh) ||
			(ax>=bx && ax<=bx+bw && ay+ah>=by && ay+ah<=by+bh) ||
			(ax+aw>=bx && ax+aw<=bx+bw && ay+ah>=by && ay+ah<=by+bh) ||
			(ax+aw>=bx && ax+aw<=bx+bw && ay>=by && ay<=by+bh)
		) {
			ax-=ball.velocityX;
			ay-=ball.velocityY;
			if (ax>=bx+bw) hRight=true;
			if (ax+aw<bx) hLeft=true;

			if (ay>by+bh) hBottom=true;
			if (ay+ah<by) hTop=true;

			if (hRight) {playSound('ping');ball.velocityX=Math.abs(ball.velocityX);}
			if (hLeft) {playSound('pong');ball.velocityX=-Math.abs(ball.velocityX);}
			if (hBottom) ball.velocityY=Math.abs(ball.velocityY);
			if (hTop) ball.velocityY=-Math.abs(ball.velocityY);

			givespin=$(this).data('accel')/(paddle.maxAccel/100);
//			window.status=givespin;

//      ball.velocityY=
		}
	});
}

function updateScore() {
	for (i=0;i<players.length;i++) {
		$('#score'+i).html(players[i].score);
	}
}

function endGame(winner) {
	$('#table').fadeOut(config.animSpeed,function() {
		$('<p class="message">Game over<span>Player '+winner+' wins!</span>Press Space for new game</p>').appendTo($('body'))
		.css({width:table.width,'margin-left':-table.width/2,'margin-top':-$('p.message').height()/2})
		.fadeIn(config.animSpeed,function() {
			table.activePlayer=-1;
		});
	});
}

function newGame() {
	table.serviceNumber=0;
	table.activePlayer=1;

	$('p.message').fadeOut(config.animSpeed,function() {
		$('#table,.paddle').remove();
		buildTable();
		$(this).remove();
	});
}

function playSound(s) {
	$('#sound').load('sound/'+s+'.mp3');
}

function rnd(a,b) {
 	return Math.round(Math.random()*(b-a))+a;
}