// Quiz engine driver
// JSLint validated JavaScript
// Copyright (c) 2009 eLearning Corner, LLC

var aQL = 10; // Number of Quiz questions to display
var bAudioStateOn = true;  // Initial audio state
var aQuizLib = [ // Images for questions
	{ 'true': 'elements/elcquizimages/dudism-no-q.png', 'false': 'elements/elcquizimages/dudism-no-a.png', bPhishing: false},
	{ 'true': 'elements/elcquizimages/capitalone-yes-q.png', 'false': 'elements/elcquizimages/capitalone-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/ebay-yes-q.png', 'false': 'elements/elcquizimages/ebay-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/boa-customer-service-yes-q.png', 'false': 'elements/elcquizimages/boa-customer-service-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/dhldelivery-yes-q.png', 'false': 'elements/elcquizimages/dhldelivery-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/paypalcreditcard-no-q.png', 'false': 'elements/elcquizimages/paypalcreditcard-no-a.png', bPhishing: false},
	{ 'true': 'elements/elcquizimages/wachovialink-yes-q.png', 'false': 'elements/elcquizimages/wachovialink-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/ups-yes-q.png', 'false': 'elements/elcquizimages/ups-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/citizensbankfraud-yes-q.png', 'false': 'elements/elcquizimages/citizensbankfraud-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/hsbconlineform-yes-q.png', 'false': 'elements/elcquizimages/hsbconlineform-yes-a.png', bPhishing: true},
	{ 'true': 'elements/elcquizimages/attbillonline-no-q.png', 'false': 'elements/elcquizimages/attbillonline-no-a.png', bPhishing: false},
	{ 'true': 'elements/elcquizimages/microsoftoutlookcriticalupdate-no-q.png', 'false': 'elements/elcquizimages/microsoftoutlookcriticalupdate-no-a.png', bPhishing: true}
];

function fnShuffle(aParm) { // shuffle any array
	for(var j, x, i = aParm.length-1; i >=0; i-- ) {
		j = parseInt(Math.random() * i, aQL);
		x = aParm[i];
		aParm[i] = aParm[j];
		aParm[j] = x;
	}
	return aParm;
}
aQuizLib = fnShuffle(aQuizLib);  // Shuffle the questions

var aAudio = {};  // Audio sounds for correct and incorrect answers
aAudio[true] = [
		'elements/audio/c1-clappingmild.output.mp3', 
		'elements/audio/c2-baseballorganandclap.output.mp3', 
		'elements/audio/c3-welldone.output.mp3',
		'elements/audio/c4-auditoriumclapping.output.mp3',
		'elements/audio/c5-youdidit.output.mp3',
		'elements/audio/c7-oohahhgroup.output.mp3',
		'elements/audio/c8-thatwhatitalkingabout.output.mp3',
		'elements/audio/c10-hallelujah.output.mp3'
		];
aAudio[false] = [
		'elements/audio/i1-smallcrowdlaughing.output.mp3',
		'elements/audio/i3-thatsridiculous.output.mp3',
		'elements/audio/i5-comeonman.output.mp3',
		'elements/audio/i7-boo.output.mp3',
		'elements/audio/i9-howcouldyoudothat.output.mp3',
		'elements/audio/i6-howlongubeenworkinhere.output.mp3'
	];

// Diagnostic functions

var fnC = function( strText ) { // Write the diagnostic string parameter to the console
	function sMs() {	 // Returns a string of 4-digit millisecond timestamp: '0000ms: '
		fnC.iT2 = fnC.iT2 || new Date().getTime();  // Initialize iT2 on first call
		fnC.iT1 = fnC.iT2;
		fnC.iT2 = new Date().getTime();
		var r = '0000' + (fnC.iT2 - fnC.iT1); // iT2-iT1 is the time since the last write
		return 	r.substring( r.length-5, r.length-1)+'ms: '; 	
	}
	fnC.bgColor = (fnC.bgColor || '#ffffff') === '#ffffff' ? '#f3f9ff':'#ffffff'; // alternate successive posts with blue or white background
	$('#console').prepend( '<div style="background-color:'+fnC.bgColor+'">'+sMs()+(strText?strText:'empty')+'</div>' ); //  push down support stack, force line break
};

// Audio functions

function fnPlayAudio( sAudio, sId, bPlay ) { // Build an audio file and play it or just load the file
	if ($('#' + sId).size() === 0 ) {
		$('<div id="'+sId+'"></div>').appendTo('#mp3Block');  // Add a div for this audio
	}
	sId = '#'+sId; // prefix the ID with the CSS selector #
	$( sId ).jPlayer( {
		    swfPath:  'elements/jplayer',
		    ready: function() { $(sId).setFile( sAudio ); if ( bPlay ) { $(sId).play(); } }
	} );
}

function fnStopAudio() {
	$("#playMe").stop();
}

function fnPlayNextAudio( iQ, bCorrect ) { // Play an as-yet appropriate correct audio sound for question number iQ which the student got "bCorrect" (right / wrong)
	if ( bAudioStateOn ) { // play nothing unless audio is on
		var sAudio = aAudio[ bCorrect ].shift();   // Take the audio from the top
		aAudio[ bCorrect ].push( sAudio ); // Push it back on the bottom
		fnPlayAudio( sAudio, 'playMe', true ); // Then play it
	}
}

function fnSetupAudio() {  // Setup audio controls and preload audio mp3s on ready
	function fnAudioSwitchText() {  // Displays the turn audio on/off text on the audio switch
		bAudioStateOn = !bAudioStateOn; // Flip the state of the audio on / off boolean
		if ( bAudioStateOn ) {
			$('#audioSwitch').text(  'Turn Audio Off' );
		} else {
			$('#audioSwitch').text( 'Turn Audio On' );
			fnStopAudio();
		}
	}
	$('#audioSwitch').click( fnAudioSwitchText ); // Define the Audio Switch onClick handler
	fnAudioSwitchText();	fnAudioSwitchText();  // Call the switch twice to retain state and set the proper text

	// Preload the audio mp3s...
	for (var i=0; i<aAudio['true'].length; i++) { // push any defined audio strings into a holding array
		fnPlayAudio( aAudio['true'][i], 'mp3C'+i, false ); 
	}
	for ( i=0; i<aAudio['false'].length; i++) { // push any defined audio strings into a holding array
		fnPlayAudio( aAudio['false'][i], 'mp3C'+i, false );
	}
}

// Quiz Review routines

var fnQReview = function fnQReview() { // Handle the queued mouseover event...
	function fnQFadeIn( oThis ) { // Fade In the proper review image
		function fnQUnqueue() {
			fnQReview.Q.shift(); // Remove the top element
			fnQReview();  // Process any remaining elements
		}
		if ( fnQReview.Q.length === 1 ) { // If this is the only queued request, go ahead and fade in the element
			var bAnswered = $(oThis).hasClass('correct') || $(oThis).hasClass('incorrect'); // If this one has been answered 
			$('#reviewImage').attr( {src: aQuizLib[ parseInt( $(oThis).text(), aQL)-1][ !bAnswered ]}).fadeIn( 'slow', fnQUnqueue ); // Fade in the new image
		} else { // We've been busy, let's stop here and go to the last element
			fnQUnqueue();
		}
	}

	var oThis = fnQReview.Q[fnQReview.Q.length-1]; // last element in queue
	if ( oThis ) { // Process any top element in the queue
		fnQReview.Q = [oThis]; // purge any forward elements, processing only the last
		if ( $('#mainImgTable img:visible').size() > 0 ) { // If there is anything visible, fade it out
			$('#mainImgTable img:visible').addClass('rememberMe').fadeOut('normal',  function() { fnQFadeIn(oThis);} ); // Fade out whatever is the visible image, Fade In the next
		} else {
			fnQFadeIn(oThis); // Just fade in the next image
		}
		$('#reviewBlock').show(); // Hide the quiz controls with a control to return to the quiz
	}
};
fnQReview.Q = [];  // Init an empty queue

function fnTrackerInit () { // Initialize the heading of the quiz page to show the question numbers 1, 2, ... 10

	$('#nTracker td').remove();  // Remove whatever Dreamweaver had there
	for (var i=1; i <= aQL; i++) { // and add a configurable (aQL) number of elements
		$('<td><span id="No'+i+'">'+i+'</span></td>').appendTo('#nTracker');	// Add next element
	}
	$('span#No1').addClass('hilight'); // Hilight the first question

	// Setup onMouseover handling of the quiz numbers
	$('#nTracker span').click( 
		function() {
			$('#nTracker span').removeClass('hover');  // remove any that may show hover
			$(this).addClass('hover'); // highlight the question under review
			if ( fnQReview.Q.push(this) === 1 ) { // first request?
				fnQReview(); // Then begin the first fade
			}
	} );
}

function fnTrackerReturn() {
	fnQReview.Q = [];  // Empty any queue
	$('#reviewBlock').hide();  // Hide the return to quiz control
	$('#nTracker span').removeClass('hover');  // remove any that may show hover
	$('#reviewImage').removeClass('rememberMe').fadeOut( 'normal', function() { $('#mainImgTable img.rememberMe').removeClass('rememberMe').fadeIn(); }); // Hide the review image, show the quiz
}

var bInProgress = false;  // Token to gate one operation at a time.

function fnChoose(oButton) { // Handler for the phishing/authentic button.  Setup to display answer and right/wrong result
	function fnShowAnswer( intQ ) { // Show an answer in a web 2.0 way
		function showQ () {
			$('img#ansImage').hide().attr( 'src', aQuizLib[ intQ-1 ][ false ] ).fadeIn('normal', function(){ bInProgress = false; }); // Fade in the answer
		}
		intQ = parseInt(intQ, 10); // Make it an integer just in case
		$('img#quizImage').fadeOut('normal', showQ ); // Fade out the Answer, callback showQ when done
	}

	if ( bInProgress ) { return false; } // Don't honor new requests until the previous event finishes
	bInProgress = true;  // This will be reset when the animation terminates
	
	var bChoice = $(oButton).attr('name') == 'Phishing';  // Phishing ?
	var sQuestion = $('#nTracker span.hilight').text(); // Get the question number
	var intQuestion = parseInt(sQuestion, 10); // integerize
	fnShowAnswer( intQuestion );

	var bCorrect = aQuizLib[ intQuestion-1 ].bPhishing;  // Correct answer
	var bStudentAns = (bCorrect === bChoice); // Student was right if both match
	if (bStudentAns) {
		$('#nTracker span.hilight').removeClass('incorrect').addClass('correct'); // Change the visual on this quiz element
		$('#feedbackControls span').text('Terrific !!!   That\'s correct !!!').removeClass('red').addClass('green');
	} else {
		$('#nTracker span.hilight').removeClass('correct').addClass('incorrect'); // Change the visual on this quiz element
		$('#feedbackControls span').text('Oops !!!   That\'s not correct !!!').removeClass('green').addClass('red');
	}
	fnPlayNextAudio( intQuestion, bStudentAns );
	$('div#questionControls').hide(); $('div#feedbackControls').show(); // Setup for the feedback display
	return false;  // return false to prevent POST
}

function fnShowQuestion( intQ ) { // Show a question in a web 2.0 way
	function showA () { 
		$('img#quizImage').hide().attr( 'src', aQuizLib[ intQ-1 ][ true ] ).fadeIn('normal', function() { bInProgress = false;}); // Fade in the question
	}
	intQ = parseInt( intQ, 10);
	$('img#ansImage').fadeOut('normal', showA ); // Fade out the Question, callback showA
}

function fnContinue() { // Handler for the "Continue" button.  Setup for the next question to display
	if ( bInProgress ) { return false; }
	bInProgress = true;  // This will be reset when the animation terminates
	$('div#feedbackControls').hide(); // Hide the feedback controls window
	var sQuestion = $('#nTracker span.hilight').text(); // Get the question number
	var intQuestion = parseInt(sQuestion, 10); // integer
	$('#nTracker span').removeClass('hilight'); // Strip any hilight classes
	if (intQuestion >= aQL) { // if no questions remain
		$('div#summaryBlock').show();  // Show the summary block
		var intNumberCorrect = $('#nTracker span.correct').size(); // Total correct
		$('div#summaryBlock span').text(intNumberCorrect.toString());  // Insert the number correct
	} else {
		intQuestion++; // Incriment to the next question
		$('span#No'+intQuestion).addClass('hilight'); // highlight the next question
		$('div#questionControls').show(); // present the question controls
		fnShowQuestion( intQuestion );
	}
	return false; // Avoid a post
}

function fnPreloadImages() {
	$(window).bind('load', function() { // sequentially preload quiz images after page loads
		var preload = [];
		for (var i=0; i< aQL; i++) { // 
			preload.push( [aQuizLib[i][ true ], 'imgQ'+i]);
			preload.push( [aQuizLib[i][ false ], 'imgA'+i]);
		} 
		$('img#preLoadQ').bind('load', function() {
			if(preload[0]) {
				var aNextP = preload.shift(); // 
				this.src = aNextP[0];
				$('<img  />').attr( { 'id': aNextP[1], 'src': aNextP[0], 'alt': ' ', 'width': 150, 'height':150 } ).appendTo('#imgBlock'); // This is unnecessary but gives an excellent html trail for support purposes
			}
		}).trigger('load'); // 1st instance of load must be triggered
	});
}

// Phishing Help
function fnPhishingHelp() {  // Setup audio controls and preload audio mp3s on ready
	var bPhishingHelp = false;  // Help isn't showing right now
	var bSliding = false;  // set to true if animation in progress
	function fnPhishingSwitch( bUp ) {  // Displays the turn audio on/off text on the audio switch
		if ( !bSliding ) { // Don't start another slide until this one is finished
			if ( !bUp || bPhishingHelp ) { // Explicit up command and help is showing
				bSliding = true; // Slide is in progress
				bPhishingHelp = !bPhishingHelp; // Set state to true if showing the help
				if ( bPhishingHelp ) {
					$('#help').text(  'Hide Help' );
					$('#mainImgTable').hide();
					$('#phishingHelp').slideDown('slow', function(){bSliding = false;});
				} else {
					$('#help').text( 'Show Help' );
					$('#phishingHelp').slideUp('slow', function(){bSliding = false;$('#mainImgTable').show();});
				}
			}
		}
	}
	$('#help').click( function(e){e.stopPropagation(); fnPhishingSwitch();} ); // Define the Phishing help onClick handler
	$('body').click( function() {fnPhishingSwitch( true ); }); //  Click anywhere and phishing help is hidden
}

// About, Feedback
function fnSetupTabs() { // Setup the About and Feedback Tabs
	$('#about').click( function() { $('#feedbackDiv').hide(); $('#aboutDiv').slideDown(); } );
	$('#aboutClose').click( function() { $('#aboutDiv').slideUp(); } );
	$('#feedback').click( function() { $('#aboutDiv').hide(); $('#feedbackDiv').slideDown(); } );
	$('#feedbackClose').click( function() { $('#feedbackDiv').slideUp(); } );
}

// Schedule things so the page renders quickly
$(document).ready(
	function() { // Take a stab at doing things in an order which will make page rendering quick
		fnShowQuestion(1); // Get the first question showing.
		fnTrackerInit(); // Initialize the page heading quiz numbers
		fnSetupTabs(); // About, Feedback
		fnPreloadImages(); // Begin downloading remaining images
		fnPhishingHelp(); // Setup phishing help page
		fnSetupAudio(); // Audio last
	}
);
