/* jQuery quiz application developed by Ari Koinuma, April 2008.  
Dependency: jquery 1.2.3

Instructions on how to use: http://infoserverwiki.publicradio.org/index.php/Quiz_Project

Be sure to set up xmlURL variable with the URL of the xml file before loading this file.
*/


// set up global variables
var correctAnswers = 0;
var skippedQuestions = 0;
var numOfQuestions;
var bodyQuizLogo, bodyQuizLogoAlt;





//Switch which div is displayed
function switchDiv(div1id, div2id) {
	$('#'+div1id).hide();
	$('#'+div2id).fadeIn(300);
}


//skip a question
function moveToNextQuestion(currentQuestionID, skipStatus) {
	if (skipStatus == true) {
		skippedQuestions = skippedQuestions+1;
	}
	var currentDivId = 'quizItem_'+currentQuestionID;
	var nextQuestionID = currentQuestionID+1;		
	if (nextQuestionID > numOfQuestions.length) {
		$('#totalAnswered').text((numOfQuestions.length-skippedQuestions));
		$('#correctAnswers').text(correctAnswers + ' ');
		nextDivId = 'quizResults';
	} else {	
		var nextDivId = 'quizItem_'+(currentQuestionID+1);
	}
	switchDiv(currentDivId, nextDivId);
}


//Evaluate an answer and give a response 
function evaluateAnswer(currentQuestionID, optionChosen, correctAnswerID) {
	//modify the skip link
	var nextLink = $('#next_'+currentQuestionID);
	
	//set up the action by first unbinding the skip function and setting it to straight move (without adding to the skipped number)
	nextLink.unbind().click(function(){
			moveToNextQuestion(currentQuestionID, false);
	})
	
	//if it's the last question, then rewrite the text to say "see results"
	if ((currentQuestionID+1)>numOfQuestions.length) {
		nextLink.text('see the results');
	} else {
		nextLink.text('next question');
	}
	
	
	
	//disable all the checkboxes
	$('.answers_for_question_'+currentQuestionID).attr('disabled', 'disabled')
	
	//stop the hovering effect below
	$('#quizItem_'+currentQuestionID).find('li').unbind('mouseover').unbind('click');
	
	var correctOption = $('#question_'+currentQuestionID+'_option_'+correctAnswerID);
	var chosenOption = $('#question_'+currentQuestionID+'_option_'+optionChosen);
	var correctIndicator = ' <span class="correct">CORRECT</span>';
	
	if (optionChosen == correctAnswerID) {
		correctOption.addClass('correctBG').append(correctIndicator);
		correctAnswers = correctAnswers+1;
	} else {
		correctOption.append(correctIndicator);
		chosenOption.addClass('incorrectBG').append(' <span class="incorrect">INCORRECT</span>');
	}
}


//Create the header div 
function headerDiv() {
	//append the logo and "question # of X"
	var hDiv = $('<div class="headerDiv"></div>');
	if (bodyQuizLogo != '') {
		hDiv.append('<img src="'+bodyQuizLogo+'" alt="'+bodyQuizLogoAlt+'" class="bodyLogo" />');
	}
	return hDiv;
}
		
	

/*Setting up the QuizItem object. 
Each quizItem would have the question, answers (array), correct answer, choices, link, and an image link.  The last two are optional. 
Choices are the multiple choices that the user gets to choose from, and the answer is the correct answer.  
To make it easy to use in this object contructor function, I'm putting the "choices" the last, as that is the only property that has more than one values (it's an array).  

*/
function QuizItem(id, question, image, imgalt, link, answer, choices) {
	//First, let's assing the first five arguments, which are simple variables.
	this.id = id; //id of the question.  Must be a number.
	this.q = question;
	this.img = image;
	this.imgalt = imgalt;
	this.link = link;
	this.ans = answer;
	//Now, let's assign the choices.  We do this by looping through the array of choices.
	this.choices = new Array(); 
	for (i=0; i<choices.length; i++) {
		this.choices[i] = choices[i];
	}  
}

//Adding a method to construct the div
QuizItem.prototype.createDiv = function(){
	//create the quiz item div
	var quizDiv = $('<div id="quizItem_'+this.id+'" class="quizItem" style="display: none;"></div>');
	
	//create the header div
	var hDiv = headerDiv();
	var stage = '<p class="quizStage">question '+this.id+' of '+numOfQuestions.length+'</p>';
	hDiv.append(stage);

		
	
	//append the image
	if (this.img != '') {
		hDiv.append('<img src="'+this.img+'" alt="'+this.imgalt+'" class="qImage">');
	}
	
	//append the header div	
	quizDiv.append(hDiv);
	
	//append the question
	quizDiv.append('<p class="question">'+this.q+'</p>');
	
	var currentQuestionID = this.id //I need to set this up ahead of time because I can't call this.id from inside another jQuery object, like the click event binding below. 
	var correctAnswer = this.ans;
	
	
	//append the answers
	var quizUL = $('<ul></ul>');
	for (i=1; i<=this.choices.length; i++) {//starting at 1 to make it more user-intuitive
		j=i-1; //compensating for the fact that the loop starts at 1, while the counting the number of questions starts at 0.
		var quizChoice = $('<li id="question_'+this.id+'_option_'+i+'"><input type="radio" name="question'+this.id+'_'+i+'"  value="'+i+'" class="answers_for_question_'+this.id+'">'+this.choices[j]+'</li>');
		
		//triggering the behavior upon choosing an answer
		quizChoice.click(function(){
				
				var thisOption = $(this).find('input:first');
				var optionChosen = thisOption.val(); 
				thisOption.attr('checked','checked');
				evaluateAnswer(currentQuestionID, optionChosen, correctAnswer);
		})
		
		//change the background.  Has to be done with JS b/c if it's done with CSS, it's hard to stop doing it when the answer is chosen
		quizChoice.mouseover(
			function(){
				$(this).addClass('hoverBG');
			}).mouseout(
			function(){
				$(this).removeClass('hoverBG');
		});
		
		quizUL.append(quizChoice);	
	}
	quizDiv.append(quizUL);
	
	var quizLinks = $('<p id="link"></p>');
	//append the link for cheating
	if (this.link != '') {
		var hintLink = '<a href="'+this.link+'" title="Hint" target="_blank">hint</a> | ';
		quizLinks.append(hintLink);
	}
	
	//append the link for skipping the question. 
	/* var quizSkip = $('<div class="skip"><a href="#" id="skip_'+this.id+'" title="Skip this question" onclick="moveToNextQuestion('+this.id+', true)">Skip this question</a></div>'); */
	
	
	var quizNext = $('<span class="quizNext" id="next_'+this.id+'">skip this question</span>').click(function(){
			moveToNextQuestion(currentQuestionID, true);
	});
	quizLinks.append(quizNext);
	
	
	quizDiv.append(quizLinks);

	
	//finally, append the quiz item div to the div in the document
	quizDiv.appendTo('#quiz');
}

function loadQuizBody(qxml, numOfQuestions){
	var i=0;
	var qI = new Array();
	
	//var qxml = $(xmlData);
	
	//alert('Number of questions is:'+numOfQuestions.length);
	while (i < numOfQuestions.length) {
		//find all instances of interaction and then assign values to the qI object.  I'm using a while loop because for some reason for loop doesn't want to work with the object creation. 
		var thisQ = $(numOfQuestions[i]);
		var id = i+1; //assigning the id of the question.  I'm starting with 1 to avoid confusion.
		var ques = thisQ.find('question').text();
		//alert(ques);
		var ans = thisQ.find('correctanswer').text();
		var link = thisQ.find('link').text();
		var img = thisQ.find('image').text();
		var imgalt = thisQ.find('imagealt').text();
		var choices = thisQ.find('option'); //this returns an array
		var choicesToAdd = new Array();
		for (j=0; j<choices.length; j++) {
			choiceValue = $(choices[j]).text();
			choicesToAdd.push(choiceValue);
		}
		var quizItem = new QuizItem(id, ques, img, imgalt, link, ans, choicesToAdd);
		qI.push(quizItem);
		//alert(qI[i].q);
		i++;
	} 
	return qI;
}


//construct the QuizIntro object.
function QuizIntro(img, imgalt, heading, text) {
	this.img = img;
	this.imgalt = imgalt;
	this.heading = heading;
	this.text = text;
}

QuizIntro.prototype.createDiv = function(){
	//create the quiz intro div
	var qIntroDiv = $('<div id="quizIntro"></div>');
	//append the image
	if (this.img != '') {
		qIntroDiv.append('<img id="introLogo" src="'+this.img+'" alt="'+this.imgalt+'">');
	}
	
	//append the intro heading
	var qIntroHeading = $('<h3 id="introHeading">'+this.heading+'</h3>/');
	qIntroDiv.append(qIntroHeading);
	
	//append the intro text
	var qIntroText = $('<p id="introText">'+this.text+'</p>');
	qIntroDiv.append(qIntroText);
	
	//create the start button
	var qIntroStart = $('<div id="startButton">start the quiz&raquo;</div>');
	qIntroDiv.append(qIntroStart);
	qIntroStart.click(function(){
			switchDiv('quizIntro', 'quizItem_1');
	});
	
	//finally, append the quiz item div to the div in the document
	qIntroDiv.appendTo('#quiz'); 
}



function loadQuizIntro(qxml) {
	//var qxml = $(xmlData);
	var intro = qxml.find('intro');
	var introimg = intro.find('image:first').text();
	var introimgalt = intro.find('imagealt:first').text();
	var introHeading = intro.find('introheading:first').text();
	var introText = intro.find('introtext:first').text();
	var quizIntro = new QuizIntro(introimg, introimgalt, introHeading, introText);
	return quizIntro;
}
	

function QuizLevel(id, lowScore, highScore, desc) {
	this.id = id;
	this.low = lowScore;
	this.high = highScore;
	this.desc = desc;
}

function loadQuizLevels(qxml) {
	//this function will be called within another function that already has xml converted to jQuery object.  So commenting out this line below.
	//var qxml = $(xmlData);
	var i=0;
	var qLevels = new Array();
	// find all levels and put them in an array
	var numOfLevels = qxml.find('level');
	while (i < numOfLevels.length) {
		//find all instances of levels and assign it to QuizLevels object.  Again, using while loop b/c of the inexplicable problem w/ object creation in for loops.
		var thisL = $(numOfLevels[i]);
		var id = i+1; //assigning the id of the level.  Gotta start that with 1. 
		var low = thisL.find('lowestscore:first').text();
		var high = thisL.find('highestscore:first').text();
		var desc = thisL.find('description').text();
		var level = new QuizLevel(id, low, high, desc);
		qLevels.push(level);
		i++;
	}
	return qLevels;
}
		
//Construct the QuizResults object.  Notice the levels argument is an array of objects. 
function QuizResults(heading, text, levels){
	this.heading = heading;
	this.text = text;
	this.levels = levels;
}
	


//Construct the div of Quiz Results
QuizResults.prototype.createDiv = function(){
	var qResultsDiv = $('<div id="quizResults" style="display: none;"></div>');
	
	//create the header div
	var hDiv = headerDiv();
	qResultsDiv.append(hDiv);
	
	//append the heading
	var qResultsHeading = $('<h3 id="resultsHeading">'+this.heading+'</h3>');
	qResultsDiv.append(qResultsHeading);
	
	//append the evaluation text. 
	var qResultsText = $('<p id="resultsText">'+this.text+'</p>');
	qResultsDiv.append(qResultsText);


	
	//append the evaluation of the user's performance.  Calculations still need to be done.
	var qEval = $('<h3 id="eval">Your score: <span id="correctAnswers"></span>  out of <span id="totalAnswered"></span>.</h3>');
	qResultsDiv.append(qEval);
	

	//append the list of levels. 
	var qLevelTable = $('<table id="levels"></table>');
	for (var i=0; i<this.levels.length; i++) {
		var qLevelScore = this.levels[i].low+'-'+this.levels[i].high+ ":";
		var qLevelRow = $('<tr id="level_'+this.levels[i].id+'"></tr>');
		qLevelRow.append('<td class="score">'+qLevelScore+'</td>');
		qLevelRow.append('<td>'+this.levels[i].desc+'</td>');
		qLevelTable.append(qLevelRow);	
	}
	qResultsDiv.append(qLevelTable);
	
	//finally, append the quiz item div to the div in the document
	qResultsDiv.appendTo('#quiz');
}


function loadQuizResults(qxml) {
	var results = qxml.find('evaluation');
	var resultHeading = results.find('evalheading:first').text();
	var resultText = results.find('evaltext:first').text();
	var levels = loadQuizLevels(qxml);
	
	var quizResults = new QuizResults(resultHeading, resultText, levels);
	return quizResults;
}


/* function testXML(xmlData) {
 var qxml = $(xmlData);	
 qxml.find('question').each(function(){
			 var q_text = $(this).text()
			 $('<li></li>')
				.html(q_text)
				.appendTo('ol');
	 });
} */


//Load the CSS for the quiz.  The URL of the CSS file should be built into the quiz tag inside the xml as an attribute "css". 
function loadQuizCSS(qxml) {
	
	var cssURL = qxml.find('quiz').attr('css'); //automatically picks the first element
	var cssTag = $('<link rel="stylesheet" type="text/css" href="'+cssURL+'" />');
	$('head').append(cssTag);
}



//master executor function
function loadQuiz(xml) {

	
	
	//first, convert the returned XMLHttpRequest object into a jQuery document
	var qxml = $(xml);
	
	//Find all questions
	numOfQuestions = qxml.find('interaction');
	
	//Assign the logo to be used for questions and results
	bodyQuizLogo = qxml.find('logoimage:first').text();
	bodyQuizLogoAlt = qxml.find('logoimagealt:first').text();

	//testXML(xml);					 
	 loadQuizCSS(qxml);
	 //load intro
	 var qIntro = loadQuizIntro(qxml);
	 qIntro.createDiv();
	 
	 //load questions
	 var qI = loadQuizBody(qxml, numOfQuestions);
	 for (var i=0; i<qI.length; i++) {
		 qI[i].createDiv();
	 }
	 
	 //load results
	 var qResults = loadQuizResults(qxml);
	 qResults.createDiv();
}

$(document).ready(function(){
		  $.ajax({
				 type: "GET",
				 url: xmlURL,
				 dataType: "xml",  
				 error: function() {
					 alert('Error loading XML document');
				 }, 
				  success: function(xml) {
					 loadQuiz(xml);
				 } 
					 
             });  //close $.ajax( 
			

			 
			 //$.get("questions.xml", testXML);
		 
});

