/* 
 * Original:
 * http://learning-computer-programming.blogspot.jp/2009/09/simple-pong-game-using-javascript.html
 */

( function( gOS, window ) {
	gOS.registerApplication( function() {
		// CHANGE THESE, IF REQUIRED
		var Speed = 5;
		// Speed of ball (pixels/step)
		var CPUSpeed = 5;
		// Speed of CPU Paddle (pixels/step)

		// Short references to objects
		var paddle1;
		var paddle2;
		var ball;
		var box;
		var msg;
		var close;
		
		// For internal use
		var dx, dy;
		// Speed in x and y directions
		var ballX, ballY;
		// x and y positions of ball
		var playerY;
		// y position of player paddle (x fixed)

		var cpuY;
		// y position of CPU paddle (x fixed)
		var iID;
		// To store ID of set interval used to clear it when required

		// Attach a function to onLoad event

		// INITIALIZE GAME OBJECTS
		function Init() {
			// Make short refrences to objects

			paddle1 = document.getElementById('paddle1');
			paddle2 = document.getElementById('paddle2');
			ball    = document.getElementById('ball');
			box     = document.getElementById('box');
			msg     = document.getElementById('msg').firstChild;
			close   = document.getElementById('pon-close');
			// Initial values
			ballX   = (box.offsetWidth / 2) - (ball.offsetWidth / 2);
			ballY   = (box.offsetHeight / 2) - (ball.offsetHeight / 2);
			cpuY    = (box.offsetHeight / 2) - (paddle2.offsetHeight / 2);
			playerY = (box.offsetHeight / 2) - (paddle1.offsetHeight / 2);
			dx = dy = Speed;

			paddle1.style.left = 20 + 'px';
			paddle1.style.top  = playerY + 'px';
			paddle2.style.left = box.offsetWidth - (20 + paddle2.offsetWidth) + 'px';
			paddle2.style.top  = cpuY + 'px';
			ball.style.left    = ballX + 'px';
			ball.style.top     = ballY + 'px';

			// Show message

			msg.data = 'Click on Paddle to Start Game.';
		}

		// START GAME
		function Start( e ) {
			//self.removeMouseEventListener( paddle1, 'click', Start );
			
			// Attach a function to onmousemove event of the box
			// box.onmousemove = MovePaddle;
			self.addEventListener( box, 'mousemove', MovePaddle );
			// Call 'GameLoop()' function every 10 milliseconds

			//iID = setInterval( GameLoop , 10 );
			
			self.addTimer( GameLoop , 10 );
			
			msg.data = '';
			return false;
		}

		// MAIN GAME LOOP, CALLED REPEATEDLY
		function GameLoop() {
			// MOVE BALL
			ballX += dx;
			ballY += dy;

			// See if ball is past player paddle

			if( ballX < 0 ) {
				// clearInterval( iID );
				self.removeTimer( GameLoop );
				iID = null;
				Init();

				//box.onmousemove = '';
				self.removeEventListener( box, 'mousemove', MovePaddle );
				msg.data = 'You Loose! Click on Paddle to Re-Start Game.';
			}

			// See if ball is past CPU paddle

			if((ballX + ball.offsetWidth) > box.offsetWidth) {
				// clearInterval(iID);
				self.removeTimer( GameLoop );
				iID = null;
				Init();

				// box.onmousemove = '';
				self.removeEventListener( box, 'mousemove', MovePaddle );

				msg.data = 'You Win!<br/>Click on Paddle to Re-Start Game.';
			}

			// COLLISION DETECTION

			// If ball hits upper or lower wall
			if(ballY < 0 || ((ballY + ball.offsetHeight) > box.offsetHeight))
				dy = -dy;
			// Make x direction opposite

			// If ball hits player paddle

			if(ballX < (paddle1.offsetLeft + paddle1.offsetWidth))
				if(((ballY + ball.offsetHeight) > playerY) && ballY < (playerY + paddle1.offsetHeight))
					dx = -dx;

			// If ball hits CPU paddle
			if((ballX + ball.offsetWidth) > paddle2.offsetLeft)
				if(((ballY + ball.offsetHeight) > cpuY) && ballY < (cpuY + paddle2.offsetHeight))
					dx = -dx;

			// Place ball at calculated positions

			ball.style.left = ballX + 'px';
			ball.style.top = ballY + 'px';

			// MOVE CPU PADDLE
			// Move paddle only if ball is coming towards the CPU paddle
			if(dx > 0) {
				if((cpuY + (paddle2.offsetHeight / 2)) > (ballY + ball.offsetHeight))
					cpuY -= CPUSpeed;
				else
					cpuY += CPUSpeed;

				paddle2.style.top = cpuY + 'px';
			}
		}

		// TO MOVE PLAYER PADDLE ON MOUSE MOVE EVENT
		function MovePaddle(e) {
			// Fetch y coordinate of mouse
			var y = (e.clientY - (box.offsetTop - document.documentElement.scrollTop));
			// Here, (box.offsetTop - document.documentElement.scrollTop) will get the relative
			// position of "box" w.r.t to current scroll postion

			// If y below lower boundary (cannot go above upper boundary -
			// mousemove event only generated when mouse is inside box
			if(y > (box.offsetHeight - paddle1.offsetHeight))
				y = (box.offsetHeight - paddle1.offsetHeight);

			// Copy position
			playerY = y;
			// Set position

			paddle1.style.top = y + 'px';
		}
		
		var self = this;
		
		this.bgColor     = '#000000';
		this.MIN_WIDTH   = 500;
		this.MIN_HEIGHT  = 300;
		this.onInit = function(){
			self.rootElement.id = 'pon-root';
			self.rootElement.innerHTML = [
				'<div id="box" style="width: 500px;height: 300px;margin: auto; border: 5px solid #FFF; position: relative; overflow: hidden;">',
					'<div style="width:24px;height:64px;background:#FFF;position:absolute;cursor:pointer;" id="paddle1"></div>',
					'<div style="width:24px;height:64px;background:#FFF;position:absolute;" id="paddle2"></div>',
					'<div style="position:absolute;color:#fff;width:32px;height:32px;font-size:32px;line-height:32px;" id="ball">●</div>',
					'<div style="position:absolute;top:120px;left:0;width:500px;text-align:center;font-size:20px;color:#fff;" id="msg" align="center">msg</div>',
				'</div>',
				'<div id="pon-close" style="width: 500px;height: 30px;margin: auto; border: 5px solid #FFF;color: #FFF;margin-top:20px;text-align:center; line-height: 30px;cursor:pointer;">close</div>'
			].join( '' );
		};
		this.onOpen = function( _w, _h ){
			winW = _w;
			winH = _h;
			
			Init();
			self.onPaneResize( _w, _h );
			
			self.addEventListener( paddle1, 'click', Start );
			self.addEventListener( close, 'click', self.close, self );
		};
		this.onPaneResize = function( _w, _h ){
			var h = Util.getElementSize( self.rootElement ).height;
			self.rootElement.style.marginTop = Math.floor( _h / 2 - h / 2 ) + 'px';
		};
		this.onClose = function(){
			// iID && clearInterval( iID );
		};
		
	}, false, true,  'pon', 'pon', null, '#1C1C1C' );
})( gOS, window );
