/*
//jQuizMe 1.0 First release 
//Documenation at www.bateru.com/jquery/jquizme/
//Please give me feedback at blarry@bateru.com
//Copyright (c) 2009 Larry Battle 3/6/2009
//Dual licensed under the MIT and GPL licenses.
//http://www.opensource.org/licenses/mit-license.php
//http://www.gnu.org/licenses/gpl.html
// quizData =[ { ques: "", ans : ""},  {ques: "", ans : ""}, etc ];
// quiz( quizData, options ) # wordsList is an arrary of objects with the following format, 
*/
// Sees if an array1 and array2 are the same.
Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length){ return false; }
	var i = this.length;	
	while( i-- ) {
        if (this[i].compare) { 
            if (!this[i].compare(testArr[i])){ return false;}
        }
        if (this[i] !== testArr[i]){ return false;}
    }
    return true;
};

(function($){
$.fn.jQuizMeDefaultLayOut = $("<div/>").attr("class","quiz-el").append( 
		$("<div/>").attr("class","q-header").append(
				$("<div/>").attr("class","q-counter")
			),
		$("<div/>").attr("class", "q-intro" ).hide(),
		$("<div/>").attr("class", "q-prob" ).append( 
			$("<div/>").attr("class","q-ques"),
			$("<div/>").attr("class","q-ans"),
			$("<div/>" ).attr( "class", "q-result" ).hide()
		),
		$("<div/>").attr( "class", "q-gameOver" ).append(
			$("<div/>").attr("class","stat"),
			$("<br />"),
			$("<div/>").attr("class","q-title"),
			$("<br /><br />"),
			$("<div/>").attr("class","q-title1"),
			$("<br /><br />"),
			$("<div/>").attr("class","q-title2"),
			$("<br /><br />"),
			$("<div/>").attr("class","q-title3"),
			$("<br />"),
			$("<div/>").attr("class","q-title4"),
			$("<br />"),
			$("<div/>").attr("class","q-title5"),
			$("<div/>").attr("class","options").append(
			)
		).hide()
	);
/*Everything is defined then called. So the starting functions are at the end.*/			
$.fn.jQuizMe = function( wordList, options ){

	var settings = jQuery.extend( {}, {
		addToEnding: " = ?",
		activeClass: "q-ol-active",
		numOfQuizQues: 3,
		help: 'None', 
		hoverClass: "q-ol-hover",
		intro : '',
		multiplyChoiceLength : 3,
		showWrongAns : true,
		random: false,
		right : 'Goed gedaan.',
		quizType : 'multipleChoiceOl', 
		title: 'In Nederland worden per week 1 a 2 kinderen met een stofwisselingsziekte geboren. Hun batterij is half leeg en laad niet meer op. In de minst ernstige vorm hebben kinderen na 50 meter lopen het gevoel dat ze een marathon te hebben afgelegd. Zij zijn dan totaal uitgeput.',
		title1: 'Bij veel kinderen zijn organen aangetast die veel energie verbruiken zoals de hersenen, het hart en de lever. Door een ernstige ontwikkelingsachterstand, epilepsie en hart- en leverfalen overlijden veel van deze kinderen voor het tiende levensjaar.',
		title2: 'Wist u dat..',
		title3: '-	Er geen behandeling is voor deze ernstige ziekten?',
		title4: '-	Er nog maar weinig mensen bekend met het bestaan en de ernst van ( energie ) stofwisselingsziekten?',
		title5: '-	Ook vanuit de farmaceutische industrie relatief weinig belangstelling is voor financiële ondersteuning naar geneesmiddelen voor energiestofwisselingaandoeningen'
	}, options );
	var isMSIE = $.browser.msie;

	return this.each( function(){
		/* currQuiz is the output file.(this is what the user sees)*/
		var currQuiz = 0, currIndex = 0, stickyEl = this, quit = false, userAns = '';
		var wList = wordList || 0;
		var wListLen = wList.length;	
		var numOfQQ = settings.numOfQuizQues;
		if( settings.multiplyChoiceLength > wListLen ){ settings.multiplyChoiceLength = wListLen;}
		if( !numOfQQ || numOfQQ > wListLen ){ numOfQQ = wListLen; }
		/*The q object is where the quiz data is stored. Everything is made before the quiz starts.*/
		var q = {
			ans: [], ansSel: [], ques: []
		};
		var stats = { 
			numOfQues: numOfQQ,
			quesTried: 0,
			/* rightAns[] and wrongAns[] keeps an index of the q's questions and answer index. So at the end the user can review their choses. */
			rightAns: [], 
			wrongAns : [],
			perc : function(){ 
				var x = Math.round( this.rightAns.length / this.numOfQues * 10000 );
				return ( x / 100); 
			},
			reset : function(){ 
				this.numOfQues = numOfQQ;
				this.quesTried = 0;
				this.rightAns = [];
				this.wrongAns = [];
			}
		};
		/* Just for no confusion: r is for random. */
		var rNum = function( len ){
			return Math.floor( Math.random() * len );
		};
		var rBool = function(){
			return ( rNum( 100 ) % 2 !== 0 );
		};
		var rAns = function( len ){
			return wList[ rNum( len || wListLen ) ].ans;
		};
		var makeArrayRandom = function( arr ){
			var j, x, i = arr.length;
			while( i ){
				j = parseInt(Math.random() * i);
				x = arr[--i]; 
				arr[i] = arr[j];
				arr[j] = x;
			}
			return arr;
		};		
		var createQuizEl = function(){
		/* Rememeber currQuiz is shown to the user, so hide until ready*/
			currQuiz = $.fn.jQuizMeDefaultLayOut.clone( true ).hide();	
			$( ".help-btn", currQuiz).toggle( 
				function(){ $( ".q-help-info", currQuiz).fadeIn( "slow" );}
				, function(){ $( ".q-help-info", currQuiz).fadeOut( "slow" );} 
			);
			$( ".quit-btn", currQuiz).click( function(){ quitQuiz(); }); 
			$( stickyEl ).append( currQuiz );	
		};
		var cont = function(){ 
			return ( !quit && ( currIndex < numOfQQ ) );
		};
		var display = function(){
			$( currQuiz ).show();
		};		
		var gameOver = function(){ 
			$( ".stat", currQuiz).text( 
				(stats.perc() + '% is goed.')
			);
			$( ".restartBtn", currQuiz).one( "click", function(){
				reStartQuiz();
			});
			$( ".deleteBtn", currQuiz).one( "click", function(){
				deleteQuiz();
			});
			$( ".q-prob, .q-intro", currQuiz).hide();
			$( ".q-gameOver", currQuiz).show();
		};
		var changeProb = function(){
			$( ".q-counter", currQuiz).text( (currIndex + 1) + '/' + numOfQQ );
			$( ".q-ques", currQuiz).html( q.ques[ currIndex ] );
			$( ".q-ans", currQuiz).html( 
			/* Checks to see if one answer selection (ansSel) element was created. This was done to save space and time in making quizTypes. */
				( q.ansSel[ currIndex ] ) ? q.ansSel[ currIndex ].clone(true) : q.ansSel[0].eq(0).clone(true) 
			);
			$( ".q-result", currQuiz ).hide();
			$( ".focusThis", currQuiz ).focus();
		};	
		var changeQuizInfo = function(){
			$( ".q-title", currQuiz).text( settings.title );
			$( ".q-title1", currQuiz).text( settings.title1 );
			$( ".q-title2", currQuiz).text( settings.title2 );
			$( ".q-title3", currQuiz).text( settings.title3 );
			$( ".q-title4", currQuiz).text( settings.title4 );
			$( ".q-title5", currQuiz).text( settings.title5 );
			$( ".q-help-info", currQuiz).html( settings.help );
			if( settings.intro ){
				$( ".q-prob", currQuiz ).hide();
				$( ".q-intro", currQuiz ).html( settings.intro ).show()
				.append( $( "<br/>" ) )
				.append( $( '<input type="button"/>' ).attr( "value", "Begin Quiz" )
					.click( function(){
						$( ".q-intro", currQuiz ).hide();
						$( ".q-prob", currQuiz ).show();
					})
				);
			}
		};
		var nextMove = function(){
			currIndex++;
			cont() ? changeProb() : gameOver();
		};
		var cAns = function( i ){ 
			return q.ans[ i || currIndex ]; 
		};		
		var checkAns = function(){
			var ans = cAns(), isAnsCorr = false;
			if( typeof ans == "object" ){
				var i = ans.length;	
				while( i-- ){
					if( userAns == ans[i] ){
						isAnsCorr = true;
					}
				}
				if( userAns == ans.toString() ){ isAnsCorr = true; }
			}
			else{
				isAnsCorr = ( userAns == ans || userAns.toString().toLowerCase() == ans.toString().toLowerCase() );
			}
			stats.quesTried++;
			( isAnsCorr ) ? stats.rightAns.push( currIndex ) : stats.wrongAns.push( currIndex );
			return isAnsCorr;
		};
		var ansResult = function(){
			var currAns = cAns();
			var isUserAnsCorr = checkAns();
			var isLongArr = (typeof currAns == "object") && (currAns.length != 1);
			var show = ( isUserAnsCorr ) ? ( settings.right ) :
							( '<br/>Juiste antwoord<br />' + (( isLongArr ) ? currAns.join( '<br/>' ) : currAns) );						
			if( !isUserAnsCorr && settings.showWrongAns ){ show = "Jouw antwoord: <br/>" + userAns + "<br/>" + show; }
			
			$( ".q-result", currQuiz ).html( show ).fadeIn( "slow" );
		};
		var hasAnsSel = function( i ){
			return ( !!wList[ i || currIndex ].ansSel );
		};
		/*The quizes are made this way. The q object is filled with the questions, answers and answer selections(what the user can choose from). 
		The user's input gets assigned to userAns ( global inside quizMe ). 
		Then nextMove() is called. Which checks to see if the user's Input is contained in the answer, or is the array.*/
		var quizTypes = {
			'multiplyChoice' : function( olVer ){
				/* multiplyChoice Quiz: 
				ques = ques;
				ansSel = <select>[ <option> is the answer + <option> * settings.multiplyChoiceLength]*/
				var makeQuesAndAns = function(){
					//var oV = olVer; // faster. Because
					var d;
					if( olVer ){
						d = $( '<div><ol class="q-ol"></ol><input type="button" class="check-btn" value="Check het antwoord"/></div>' );
						$( ".q-ol-li", d )
							.live( "click", function( e ){
								$( ".check-btn", currQuiz).attr( "disabled", false );
								var val = parseInt( $( e.target ).attr( "val" ), 10 );
								/* If the user's answer(userAns) is array, only one of the elements is needed for checkAns to return true.*/
								userAns = ( isNaN( val ) ) ? $( e.target ).text() :
											( typeof wList[ val ].ans == "object") ? wList[ val ].ans[0] :
												wList[ val ].ans;
								$( "." + settings.activeClass, currQuiz ).removeClass( settings.activeClass );
								$( e.target ).addClass( settings.activeClass );
							})
							.live( "mouseover", function( e ){ 
								$( e.target ).addClass( settings.hoverClass );
							})
							.live( "mouseout", function( e ){
								$( e.target ).removeClass( settings.hoverClass );
							});
					}
					else{
						d = $( '<div><select class="q-select"></select><input type="button" class="check-btn" value="Check het antwoord"/></div>' );
						$( ".q-select", d ).bind( "click keypress", function( e ){
							$( ".check-btn", currQuiz).attr( "disabled", false );
							var val = parseInt( $(e.target).val(), 10 );
							/* If the user's answer(userAns) is array, only one of the elements is needed for checkAns to return true.*/
							userAns = ( isNaN( val ) ) ? $( "option:selected", this ).text() : 
										( typeof wList[ val ].ans == "object") ? wList[ val ].ans[0] :
											wList[ val ].ans;
						});
					}
					$( ".check-btn", d ).attr( "disabled", true ).one( "click", function(){ 
						$( this ).attr("value", "Volgende").one( "click", function(){ 
							nextMove(); 
						});
						ansResult();
					});
					var setLen = settings.multiplyChoiceLength;
					var i = numOfQQ;
					var ansPos, optHtml, val, len;
					var wListRange = [], j = wListLen;
					while( j-- ){
						wListRange[ j ] = j;
					}
					
					while( i-- ){
						optHtml = "";
						if( hasAnsSel( i ) ){
							val = [];
							if( typeof wList[ i ].ansSel == "object" ){ 
								val = wList[ i ].ansSel.concat();
								len = val.length + 1;
							}
							else{
								val[ 0 ] = wList[ i ].ansSel;
								len = 2;
							}
							val[ val.length ] = wList[ i ].ans;
							makeArrayRandom( val );
							
							while( len-- ){
								optHtml += ( olVer ) ? ["<li class = 'q-ol-li' >", val[ len ], "</li> "].join("") :
												[ "<option value='n", i ,"'>", val[ len ], "</option> " ].join("");
							}
						}
						else{
							var randAns = wListRange.concat();
							randAns.splice( i, 1 ); // From the answer Index from randAns. 
							len = setLen;
							ansPos = rNum( len );
							while( len-- ){
								var randIndex = rNum( randAns.length );
								val = ( len == ansPos ) ? i : randAns.splice( randIndex, 1 ) || 0;
								optHtml += ( olVer ) ? ["<li class = 'q-ol-li' val ='", val, "'>", wList[ val ].ans, "</li> "].join("") :
												[ "<option value =' ", val, " '>", wList[ val ].ans, "</option> " ].join("");
							}
						}
						/*below: innerHTML is 2x faster than $.html() but IE generates corrrupt option html*/
						( olVer ) ? $( ".q-ol", d )[0].innerHTML = optHtml :
						( isMSIE ) ? $( "select", d ).html( optHtml ) : $( "select", d )[0].innerHTML = optHtml;
						q.ansSel[ i ] = d.clone( true );
						q.ques[ i ] = wList[ i ].ques;
						q.ans[ i ] = wList[ i ].ans;
					}
				};
				makeQuesAndAns();
			},
			'multiplyChoiceOl' : function(){
				/* multiplyChoiceOlQuiz: ques = ques, ansSel = ol [ <list> real ans + <list> * settings.multipleChooseLength] */
				this.multiplyChoice(true);
			}
		};
		var makeQuizType = function(){ 
				( quizTypes[ settings.quizType ] ) ? quizTypes[ settings.quizType ]() : quizTypes.fillInTheBlank();
		};
		var quitQuiz = function(){ 
			quit = true; 
			nextMove();
		};	
		var createNewQuiz = function(){
			if( settings.random ){ makeArrayRandom( wList ); }
			stats.reset();
			makeQuizType();
			changeQuizInfo();
			changeProb();
			display();
		};
		var deleteQuiz = function(){
			$( currQuiz ).remove();
			q = {};
		};
		var reStartQuiz = function(){
			$( currQuiz ).hide();
			$( ".q-gameOver", currQuiz ).hide();
			$( ".q-prob", currQuiz ).show();
			quit = false;
			currIndex = 0;
			createNewQuiz();
		};
		var start = function( el ){
			if( !el ){ return false; }
			stickyEl = el;
			if( !wListLen ){ 
				currQuiz = $( "<p/>" ).text( "Error: Empty word list." ); 
				display();
				return currQuiz;
			}
			createQuizEl();
			createNewQuiz();
			return currQuiz;
		};		
		start( this );	//This is where it all starts.
	});
};
})(jQuery);