/**
 * Cover the Red Spot
 * Based on code from http://www.smart-kit.com/games/game2/
 * Heavily adapted for better cross-browser support and a smoother UI
 * @author   Travis Miller
 *
 * @TODO build admin tool
 */
var RedSpot = function() {

	var pub = {};
	
	var defaultName = "As registered for the conference.";
	var defaultPhone = "To contact if you are a winner.";
	var defaultEmail = "As registered for the conference.";
	
	var currentPlayerId = null;
	var loadingDiv = null;
	var mainDiv = null;
	var scoreboardDiv = null;
	var scoreboardTbody = null;
	var registerDiv = null;
	var registerForm = null;
	var registerSubmit = null;
	var registerName = null;
	var registerPhone = null;
	var registerEmail = null;
	var registerWebinar = null;
	var gameDiv = null;
	var gameName = null;
	var gameScore = null;
	//var gameTime = null;
	var gameStart = null;
	var gameDone = null;
	var timer = null;

	var pub = {};
	var targetDiameter = 297;
	var targetRadius = ( targetDiameter - 1 ) / 2;
	var targetArea = 68777;
	var solutionDiameter = 181;
	var solutionRadius = ( solutionDiameter - 1 ) / 2;

	var score;
	var discsRemaining;
	var cxArray = new Array(5);
	var cyArray = new Array(5);
	var pArray = new Array( targetDiameter * targetDiameter );

	var startTime = null;
	var endTime = null;
	
	var processRegistration = function() {
	
		var emailRegEx = new RegExp( "^.+@.+\..{2,6}$" );
	
		if ( $(registerName).val() == defaultName ) {
			$(registerName).focus();
			alert( "Please enter your full name." );
		} else if ( $(registerPhone).val() == defaultPhone ) {
			$(registerPhone).focus();
			alert( "Please enter your cell phone number." );
		} else if ( $(registerEmail).val() == "" ) {
			$(registerEmail).focus();
			alert( "Please enter your email address." );
		} else if ( !emailRegEx.test( $(registerEmail).val() ) ) {
			$(registerEmail).select();
			alert( "The email address you entered is not valid. Email addresses take the form someone@somewhere.com." );
		} else {
		
			// data looks good; submit it to the server
			
			$(registerName).attr( "disabled", "disabled" );
			$(registerPhone).attr( "disabled", "disabled" );
			$(registerEmail).attr( "disabled", "disabled" );
			$(registerWebinar).attr( "disabled", "disabled" );
			
			$.ajax( {
				type: "POST",
				url: "register.php",
				data: {
					name: $(registerName).val(),
					phone: $(registerPhone).val(),
					email: $(registerEmail).val(),
					webinar: ( $(registerWebinar).attr( "checked" ) ? 1 : 0 )
				},
				success: receiveRegistrationReply
			} );
						
		}
	
	};
	
	var receiveRegistrationReply = function( playerId ) {

		if ( playerId == 0 ) {
		
			// OH SNAP!
			
			alert( "Sorry, but you have already played today." );
		
			$(registerName).val( "" );
			$(registerPhone).val( "" );
			$(registerEmail).val( "" );
			$(registerWebinar).val( "" );
		
		} else {
		
			// we got a valid player ID 
			
			currentPlayerId = playerId;
			
			resetDiscs();
			randomizeDiscs();
			$(gameName).html( $(registerName).val() );
			$(registerDiv).hide();
			$(gameStart).show();
			$(gameDone).hide();
			$(gameScore).html( "0.00" );
			//$(gameTime).html( "0.00" );
			$(gameDiv).show();

		}

		$(registerName).removeAttr( "disabled" );
		$(registerPhone).removeAttr( "disabled" );
		$(registerEmail).removeAttr( "disabled" );
		$(registerWebinar).removeAttr( "disabled" );

	};
	
	var randomizeDiscs = function() {
	
		var discsArray = [ 1, 2, 3, 4 ].sort( function() { return 0.5 - Math.random(); } );
		
		for ( var i = 1; i <= 4; i++ ) {
			document.getElementById( "solution-disc-" + i ).src = "images/solution_disc_" + discsArray.pop() + ".png";
		}
	
	};
	
	var startGame = function() {
		
		if ( timer != null ) {
			window.clearInterval( timer );
			timer = null;
		}
		
		score = 0;
		$(gameScore).html( "0.00" );
		//$(gameTime).html( "0.00" );

		discsRemaining = 5;
		resetDiscs();
		
		for ( var i = 0; i < targetDiameter; i++ ) {
			for ( var j = 0; j < targetDiameter; j++ ) {
				if ( pArray[ i * targetDiameter + j ] > 0 ) {
					pArray[ i * targetDiameter + j ] = 1;
				}
			}
		}
		
		$(gameStart).hide();
		$(gameRestart).show();
		
		// destroy any draggables and droppables that might have been created
		// in previous playthroughs
		
		$(".solution-disc").draggable( "destroy" );
		$("#target-disc").droppable( "destroy" );
		
		// create draggables and droppables
	
		$(".solution-disc").draggable( {
			revert: "invalid",
			stack: { group: ".solution-disc", min: 1 }
		} );
	
		$("#target-disc").droppable( {
			accept: ".solution-disc",
			drop: scoreDisc
		} );

		startTime = new Date();
		startTime = startTime.getTime();
		
		timer = window.setInterval( function() {
			var now = new Date();
			//$(gameTime).text( roundTime( now.getTime() - startTime ) );
		}, 100 );
		
	};
	
	var scoreDisc = function( e, ui ) {
				
		// render this disc undraggable
		$(ui.draggable).draggable( "destroy" );
		
		// calculate score
		
		var s = 0;

		// get the absolute positions of the target disc and the
		// solution disc

		var targetOffset = $("#target-disc").offset();
		var targetTop = targetOffset.top;
		var targetLeft = targetOffset.left;
		
		var solutionTop = ui.absolutePosition.top;
		var solutionLeft = ui.absolutePosition.left;
		
		// calculate the center point of the solution disc, relative
		// to the upper left corner of the target disc
		
		var cx = solutionLeft + solutionRadius - targetLeft;
		var cy = solutionTop + solutionRadius - targetTop;
		cxArray[ 5 - discsRemaining ] = cx;
		cyArray[ 5 - discsRemaining ] = cy;
		
		//alert( 'cx: ' + cx + '; cy: ' + cy );
		
		for ( var i = 0; i < targetDiameter; i++ ) {
			for ( var j = 0; j < targetDiameter; j++ ) {

				if ( pArray[ i * targetDiameter + j ] == 1 ) {
		
					var cxx = i - cx;
					var cyy = j - cy;
		
					if ( cxx * cxx + cyy * cyy <= solutionRadius * solutionRadius ) {
						pArray[ i * targetDiameter + j ] = 2;
						s++;
					}
				} else if ( pArray[ i * targetDiameter + j ] == 2 ) {
					s++;
				}
			}
		}
		
		score = Math.floor( 10000 * s / targetArea ) / 100;
		rest = targetArea - s;
		
		$(gameScore).html( score );
		discsRemaining--;
		
		if ( discsRemaining == 0 ) {	
			finishedGame();
		}

	};
	
	var resetDiscs = function() {
		
		for ( var i = 1; i <= 5; i++ ) {
			$( "#solution-disc-" + i ).css( "left", "358px" );
			$( "#solution-disc-" + i ).css( "top", "179px" );
		}
		
		$( "#solution-disc-5" ).css( "z-index", -255 );
		
	};
	
	var finishedGame = function() {
	
		endTime = new Date();
		endTime = endTime.getTime();
		var finalTime = roundTime( endTime - startTime );
	
		// stop the timer
		window.clearInterval( timer );
		timer = null;
		//$(gameTime).text = finalTime;
		
		// make things flash
		$(gameScore).animate( { color: "yellow" }, 500, function() {
			$(gameScore).animate( { color: "black" }, 500 );
		} );
		//$(gameTime).animate( { color: "yellow" }, 500, function() {
		//	$(gameTime).animate( { color: "black" }, 500 );
		//} );
		
		$(gameDone).show();		
		
		submitScore(
			score,
			finalTime,
			currentPlayerId
		);
	
	};
	
	var roundTime = function( ms ) {
		return ( Math.round( ms / 10 ) / 100 ).toFixed( 2 ) ;
	};
	
	var donePlaying = function() {
	
		if ( timer != null ) {
			window.clearInterval( timer );
		}
		pub.init();
	
	};
	
	var submitScore = function( score, time, playerId ) {
	
		$.ajax( {
			type: "POST",
			url: "save_score.php",
			data: {
				score: score,
				time: time,
				player_id: playerId
			},
			success: requestHighScores
		} );
	
	};
	
	var requestHighScores = function() {
		
		$.ajax( {
			url: "get_high_scores.php",
			dataType: "json",
			success: receiveHighScores
		} );
		
	};
	
	var receiveHighScores = function( scores ) {
	
		var rows = "";
		var thisTime = null;

		for ( var i = 0; i < scores.length; i++ ) {
		
			thisTime = ( scores[i].time ).toFixed( 2 );
		
			rows += '<tr>';
			rows += '<td>' + scores[i].name + '</td>';
			rows += '<td>' + scores[i].score.toFixed( 2 ) + '%</td>';
			//rows += '<td>' + thisTime + 's</td>';
			rows += '<td>' + scores[i].date + '</td>';
			rows += '</tr>';
		
		}
		
		$(scoreboardTbody).html( rows );
	
	};
	
	var resizeScoreboard = function() {
		var newHeight = $(window).height() - 31 - 204; // black stripe, header image
		$(scoreboardDiv).height( newHeight + "px" ); 
	};
	
	pub.init = function() {
	
		// set handles for various DOM nodes
	
		currentPlayerId = null;
		loadingDiv = $("#loading");
		mainDiv = $("#main");
		scoreboardDiv = $("#scoreboard");
		scoreboardTbody = $("#scoreboard-tbody");
		registerDiv = $("#register");
		registerForm = $("#register-form");
		registerSubmit = $("#register-submit");
		registerName = $("#name");
		registerPhone = $("#phone");
		registerEmail = $("#email");
		registerWebinar = $("#webinar");
		gameDiv = $("#game");
		gameName = $("#game-name");
		gameScore = $("#game-score");
		//gameTime = $("#game-time");
		gameStart = $("#game-start");
		gameRestart = $("#game-restart");
		gameDone = $("#game-done");
		
		// prevent submission of the registration form

		$(registerForm).submit( function() { return false; } );
		$(registerSubmit).click( processRegistration );
		
		// set up behaviors for "Full Name" field
		
		$(registerName).val( defaultName );
		$(registerName).addClass( "default" ); 
		
		$(registerName).focus( function() {
			if ( $(this).val() == defaultName ) {
				$(this).val( "" );
				$(this).removeClass( "default" );
			}
		} );
		
		$(registerName).blur( function() {
			if ( $(this).val() == "" ) {
				$(this).val( defaultName );
				$(this).addClass( "default" );
			}
		} );

		// set up behaviors for "Cell Phone" field
		
		$(registerPhone).val( defaultPhone );
		$(registerPhone).addClass( "default" ); 
		
		$(registerPhone).focus( function() {
			if ( $(this).val() == defaultPhone ) {
				$(this).val( "" );
				$(this).removeClass( "default" );
			}
		} );
		
		$(registerPhone).blur( function() {
			if ( $(this).val() == "" ) {
				$(this).val( defaultPhone );
				$(this).addClass( "default" );
			}
		} );
		
		// set up behaviors for the "Email" field
		
		$(registerEmail).val( defaultEmail );
		$(registerEmail).addClass( "default" ); 
		
		$(registerEmail).focus( function() {
			if ( $(this).val() == defaultEmail ) {
				$(this).val( "" );
				$(this).removeClass( "default" );
			}
		} );
		
		$(registerEmail).blur( function() {
			if ( $(this).val() == "" ) {
				$(this).val( defaultEmail );
				$(this).addClass( "default" );
			}
		} );
		
		// clear the opt-in checkbox

		$(registerWebinar).removeAttr( "checked" );

		// initialize pArray
		
		for ( var i = 0; i < targetDiameter; i++ ) {
			for ( var j = 0; j < targetDiameter; j++ ) {
				if ( ( i - targetRadius ) * ( i - targetRadius ) + ( j - targetRadius ) * ( j - targetRadius ) <= targetRadius * targetRadius ) {
					pArray[ i * targetDiameter + j ] = 1;
				} else {
					pArray[ i * targetDiameter + j ] = 0;
				}
			}
		}

		// register behaviors for "Start", "Restart", and "Done Playing" buttons
		$(gameStart).click( startGame );
		$(gameRestart).click( startGame );
		$(gameRestart).hide();
		$(gameDone).click( donePlaying );

		requestHighScores();
		resizeScoreboard();
		$(window).resize( resizeScoreboard );
		
		$(loadingDiv).hide();
		$(mainDiv).show();
		$(registerDiv).show();
		$(gameDiv).hide();
		$(scoreboardDiv).show();
	
	};
	
	return pub;

}();

$( function() {
	RedSpot.init();
} );