//
// Internal Variables
//

var questionGroupsArray = new Array();	// any array of an array of questions, sorted 
var questions = new Array();		// array containing all the questions
var questionsCorrect = 0;			// count of correct questions
var questionsIncorrect = 0;		// count of incorrect questions
var questionCount = 0;				// used to generate a subset of question of al the questions, e.g. if 1000 questions listed, you may want a quiz of 50 questions
var passPct = 100;					// Percentage score to pass the test
var htmlWelcome = "";				// the welcome message (start-screen)
var finalScores = new Array();		// array for holding the final score gimic
var groupScore = new Array();		// used to keep a record of group scores 


//
// Question Group
//

function AddQuestionGroup( groupName, questionsArray )
{
	questionGroupsArray[questionGroupsArray.length] = new QuestionGroup( groupName, questionsArray );
}

function QuestionGroup( groupName, questionsArray )
{
	this.GroupName = groupName;
	this.QuestionsArray = questionsArray;
	return this;
}

//
// Updates a group with an answer; e.g. groupName = "airlaw", false means a question on airlaw was answered incorrectly
//
function GroupAnswer( groupName, boolCorrect )
{
	// first determine if the group name is in the array?
	found = false;
	for( i =0; i<groupScore.length; i++ )
	{
		if( groupScore[i].Name == groupName )
		{
			found = true;
			break;
		}
	}
	if( !found )
	{
		// create new group now
		groupScore[groupScore.length] = new CreateNewScoreGroup( groupName );
	}
	
	// update the group score
	for( i =0; i<groupScore.length; i++ )
	{
		if( groupScore[i].Name == groupName )
		{
			if( boolCorrect )
				groupScore[i].Correct++;
			else
				groupScore[i].Incorrect++;
			break;
		}
	}	
}

// 
// Function to report group scores (returns a string of html)
//
function GroupReport()
{
	html = "";
	html+='<table width="70%" border="0" cellpadding="0" cellspacing="1">';
	for( i =0; i<groupScore.length; i++ )
	{
		html+='<tr>';
		
		count = groupScore[i].Correct+groupScore[i].Incorrect;
		pctGood = parseInt((groupScore[i].Correct/count)*100);
		pctBad = 100 - pctGood;
		
		html+='<td width="30%">'+groupScore[i].Name+' ('+pctGood+'%)</td>';
		
		html+='<td width="60%">';
		if( pctGood != 0 )
			html+='<img src="/images/barGreen.gif" height="20px" title="'+groupScore[i].Correct+' corrrect" width="'+pctGood+'%" />';
			
		if( pctBad != 0 )
			html+='<img src="/images/barRed.gif" height="20px" title="'+groupScore[i].Incorrect+' incorrect" width="'+pctBad+'%" />';
			
		html+='</td>';
		html+='<td width="10%">&nbsp;&nbsp;';
		if( pctGood > 70 )
		{
			html+='<img src="/images/cheer.gif" />';
		}
		else if (pctGood < 30 )
		{
			html+='<img src="/images/faint.gif" />';
		}
		else
		{
			html+='<img src="/images/popcorn.gif" />';
		}
		html+='</td>';
		html+='</tr>';
		
		/*
		html+= "Group: " + groupScore[i].Name;
		html+= "<br/>";
		count = groupScore[i].Correct+groupScore[i].Incorrect;
		html+= "Total Questions: " + (count);
		html+= "<br/>";
		if( count != 0 )
		{
			html+= "Percentage: " + parseInt((groupScore[i].Correct/count)*100);
			html+= "<br/>";
		}
		*/
	}
	html+='</table>';
	return html;
}

//
// Support function for creating a new score group
//
function CreateNewScoreGroup( name )
{
	this.Name = name;
	this.Correct = 0;
	this.Incorrect = 0;
	return this;
}


//
// Add a final score rating 
//
function AddScore( objScorePicture )
{
	var index = finalScores.length;
	finalScores[index] = objScorePicture;
}

//
// Create a score picture
//

function CreateScorePicture( percentageFrom, percentageTo, htmlMessage )
{
	this.PercentageFrom = percentageFrom;
	this.PercentageTo = percentageTo;
	this.HtmlMessage = htmlMessage;
	return this;
}

//
// When all the questions are defined, this method is invoked to start the test
//

function InitialiseTest(
	testName, 		// the name of the test
	welcomeMessage,	// test to display at the start of the test
	numQuestions,	// how many questions you want to run through
	passMark		// the percentage of questions for a pass
	)
{

	questionCount = numQuestions;
	passPct = passMark;
	
	InitialiseQuestions();
	
	// do a test of question availability; i.e. are too many questions being requested?
	numberSections = questionGroupsArray.length;
	for( i=0; i<numberSections; i++ )
	{
		// debug test
		if( numberQuestions < questionCount/numberSections )
		{
			alert("Warning: Insufficient questions in section: " +  questionGroupsArray[i].GroupName + ".  It only contains " + numberQuestions + " questions and " + questionCount/numberSections + " are required." );
			questionCount = numberQuestions/numberSections;
		}
	}
	
	
	var html="";

	html+=welcomeMessage;
	html+='<p><img src="/images/start-button.gif" alt="Start" onclick="RenderQuestion(0);" /></p>';
	
	if( numQuestions > questions.length ) numQuestions = questions.length;
	
	// details about the question library - how many questions are there in total?
	libraryQuestions = 0;
	sections = 0;
	for(i=0;i<questionGroupsArray.length; i++)
	{
		libraryQuestions+= questionGroupsArray[i].QuestionsArray.length;
		sections++;
	}
	

	html+='<p><small>Pass: '+passPct+'% Total Questions in Test: '+questionCount+' Library Questions: '+libraryQuestions+' Sections in Test: '+sections+'.</small></p>';
	
	// create placeholder in the document for the test
	document.write('<div class="test" id="questionArea">'+html+'</div>');
	
	htmlWelcome = html; //remember this html ready for restart
}

//
// Restarts the exam again
//

function Restart()
{
	// jumble up the questions
	InitialiseQuestions();
	
	
	// reset counters
	questionsCorrect = 0;
	questionsIncorrect = 0;
	
	// reset groups score tracking
	groupScore = new Array();
	
	$("#questionArea").fadeOut(400, function()
		{
			$("#questionArea").html(htmlWelcome);
			$("#questionArea").fadeIn(400);
		}
	);
}

function InitialiseQuestions()
{
	//questions.sort( randOrd ); // old method
	
	// randomise the question in each section 
	for( i=0; i<questionGroupsArray.length; i++ )
	{
		questionGroupsArray[i].QuestionsArray.sort( randOrd );
	}
	
	// add 10 questions from each section into main array
	questions = new Array(); // fresh array
	
	numberSections = questionGroupsArray.length;
	
	for( i=0; i<numberSections; i++ )
	{
		numberQuestions = questionGroupsArray[i].QuestionsArray.length;

		// debug test
		if( numberQuestions < questionCount/numberSections )
		{
			alert("Warning: Insufficient questions in section: " +  questionGroupsArray[i].GroupName + ".  It only contains " + numberQuestions + " questions and " + questionCount/numberSections + " are required." );
		}
		else
		{
			// calculate how many questions to use from this section.
			numberQuestions = questionCount/numberSections;
		}
		
		for(q=0; q<numberQuestions; q++)
		{
			ArrayAdd( questions, questionGroupsArray[i].QuestionsArray[q] );
		}
	}
}


//
// Utility method to add a new Question to the test
//

function CreateQuestion(
	strTopic,
	htmlQuestion,
	arrayAnswers,
	randomiseAnswers // optional parameter
	)
{

	// jumble the answers around so it looks different if running through again later
	if( typeof(randomiseAnswers) == "undefined" )
	{
		arrayAnswers.sort( randOrd );
	}
	else if(randomiseAnswers == true )
	{
		arrayAnswers.sort( randOrd );
	}
	
	// is this a multi answer question?
	var correctAnswerCount = 0;
	for( i=0; i<arrayAnswers.length; i++ )
	{
		if( arrayAnswers[i].Correct ) correctAnswerCount++;
	}
	
	this.Topic = strTopic;
	this.Question = htmlQuestion;
	this.Answers = arrayAnswers;
	this.MultiAnswer = correctAnswerCount>1;
	this.Correct = false;	
	return this;
}

//
// Utility method for adding answers to a single question
//

function CreateAnswer(
	htmlAnswer,				// html describing the one answer option
	boolIsCorrectAnswer,	// true if this option is the correct answer
	htmlExtraInfo			// extra information explaining the answer
)
{
	this.Answer = htmlAnswer;				// text describing one of the answer choices
	this.Correct = boolIsCorrectAnswer;	// set True if this is a correct answer (note: can have multiple correct statements)
	this.ExtraInfo = htmlExtraInfo;		// used to explain a correct answer (for test review at the end - optional)
	this.ActualAnswer = false;			// used to track what the user actually answererd - end of test review
	return this;
}

//
// support function to help randomise arrays
//

function randOrd()
{
	return (Math.round(Math.random())-0.5);
}

//
// Validate the results before proceeding to the next question of end of the test
//

function Submit(form)
{
	// how well was the current question answered?
	index = parseInt( form.elements["index"].value );
	question = questions[index];
	
	// scan the answers
	correct = true;		// assume everthing correct to start with
	numAnswers = 0;			// count of how many true answers there are
	answersSelected = 0;	// count of how many choices were selected
	for( i=0; i<question.Answers.length; i++)
	{
		// record user response to this question for later analysis
		question.Answers[i].ActualAnswer = form.elements["answer"+i].checked;
		
		if( question.Answers[i].ActualAnswer)
		{
			// record this answer in the array
			answersSelected++;
			// is this answer incorrect?
			if( !question.Answers[i].Correct ) correct = false; // answered this incorrectly
		}
		else
		{
			// was this a correct answer that was answered false?
			if( question.Answers[i].Correct == true ) correct = false;
		}
		
		// count the number of correct anwers to the question 
		if( question.Answers[i].Correct ) numAnswers++;
	}
	
	// validate logic for moving forwards
	if( numAnswers == 1 && answersSelected != 1)
	{
		// don't give away how many actual answers there are; just hint that one or more is correct!
		alert("Please select one answer to proceed." );
		return false;
	}	
	
	if( answersSelected == 0 )
	{
		// at least one answer is always required!
		alert("Please select one or more answers to proceed." );
		return false;
	}
		
	// how did they do?
	question.Correct = correct;
	if( correct )
		questionsCorrect++;
	else
		questionsIncorrect++;
		
	// record the group score...
	GroupAnswer( question.Topic, question.Correct );
	
	// check if at end
	index++; // move to next question
	if( index < questionCount )
	{
		RenderQuestion(index);
	}
	else
	{
		// end of quiz
		$("#questionArea").hide(200, function()
			{
				// final score - result analysis
				var html = "";
				var pct = parseInt((questionsCorrect/questionCount)*100);
				html+= '<p align="center"><b>You have reached the end of the quiz scoring<br/><br/><big>'+pct+'%</big></b></p>';
				
				var Caption = "";
				var ImageUrl = "";
				
				for( i=0; i<finalScores.length; i++)
				{
					var score = finalScores[i];			
					if( (pct >= parseInt(score.PercentageFrom))  &&  (pct <= parseInt(score.PercentageTo)) )
					{					
						html+='<p>'+score.HtmlMessage+'</p>';
						break;
					}
				}
				
				
				html+= "<p><u>Results Analysis</u></p>\n";
				
				html+=GroupReport();
				
				currentSection = "";
				
				for( i=0; i<questionCount; i++)
				{
					var question = questions[i];
					var answers = question.Answers;
					
					if( currentSection != question.Topic )
					{
						// new section heading
						currentSection = question.Topic;
						html+='<h3>' + currentSection +'</h3>';
					}
					
					html+='<p><small>\n';
					html+='<b>Question '+(i+1)+':</b> '+question.Question+'\n';
					
					if( question.Correct )
						html+= ' <img src="/images/tick.gif" />';
					else
						html+= ' <img src="/images/cross.gif" /> <b>WRONG!</b>';						
						
					if( question.MultiAnswer )	html+=' Multiple Answers Required\n';
					
					if( !question.Correct )
					{
						// users answers...
						html+='<br />&nbsp;&nbsp;&nbsp;You answered:<br />\n';
						html+='<ul style="padding=top: 0px; margin-top: 0px; padding-bottom: 2px; margin-bottom: 0px;">';
						for( a=0; a< answers.length; a++ )
						{
							if( answers[a].ActualAnswer )
							{
								// this is one their answer
								html+='<li><small>';
								html+=answers[a].Answer;
								if( answers[a].Correct )
								{
									html+= ' <img src="/images/tick.gif" />'; 	// this was the correct answer
								}
								else
								{
									// this was the wrong answer
									html+= ' <img src="/images/cross.gif" />';
									
									// explanation why this was wrong?
									if( answers[a].ExtraInfo != "" )
									{
										html+='<br /><i>'+answers[a].ExtraInfo+'</i>';
									}
								}
								html+='</small></li>';
							}
						}
						html+='</ul>';
					}
					
					
					//
					// Show the correct answers now
					//
					
					if( question.MultiAnswer )
						html+='<div><small>&nbsp;&nbsp;&nbsp;The correct answers were:<br />';
					else
						html+='<div><small>&nbsp;&nbsp;&nbsp;The correct answer was:<br />';
						
					html+='<ul style="padding=top: 0px; margin-top: 0px; padding-bottom: 2px; margin-bottom: 0px;">';
					for( a=0; a< answers.length; a++ )
					{
						if( answers[a].Correct )
						{
							html+="<li><small>";
							html+=answers[a].Answer;
							html+= ' <img src="/images/tick.gif" /></small></li>'; 	// this was the correct answer
						}
					}
					html+='</ul></small></div>';
					html+='</small></p>';
				}
				
				// render a restart button
				html+='<p><img src="/images/restart-button.gif" alt="Start" onclick="Restart();" /></p>';
				
				$("#questionArea").html(html);
				$("#questionArea").slideDown(400);
			}
		);
	}
		
	return false;
}


//
// Places a new question by fading out the old one and fading in the new one
//

function RenderQuestion( index )
{
	$("#questionArea").fadeOut(400, function()
		{
			question = questions[index];
			var html = "";

			html+='<b>Question '+(index+1)+' of '+(questionCount)+': '+question.Topic+'</b>\n';
			html+="<p>"+question.Question+"</p>\n";

			// answers
			var numberOfCorrectQuestions = 0;
			
			for( var i=0; i<question.Answers.length; i++ )
				if( question.Answers[i].Correct ) numberOfCorrectQuestions++;
			if( numberOfCorrectQuestions > 1 )
				html+='<p><small>One or more of the statements below are correct, select the correct ones.</small></p>';
		
			html+='<form>\n';
			html+='<input type="hidden" name="index" value="'+index+'">\n';
			html+='<table>\n';
			for( var i=0; i<question.Answers.length; i++ )
			{
				html+='<tr><td valign="middle">\n';
				html+='<input type="checkbox" name="answer'+i+'" />\n';		
				html+='</td><td>\n';				
				html+=question.Answers[i].Answer;
				html+='</td></tr>\n';
			}
			html+='</table>';	
			html+='<p><input type="image" src="/images/next-button.gif" onclick="return Submit(this.form);" /></p>';
			html+="</form>";
			
			//html+='DEBUG: Correct: ' + questionsCorrect + " Incorrect: " + questionsIncorrect + " Count: " + (questionsCorrect+questionsIncorrect) + " PCT: " +(questionsCorrect/(questionsCorrect+questionsIncorrect))*100;

			$("#questionArea").html(html);
			$("#questionArea").fadeIn(200);
		}
	);
}

// Adds an element to an array
function ArrayAdd( array, element )
{
	var index = array.length;
	array[index] = element;
}

//
// Adds a question to the array
//
function AddQuestion( question )
{
	var index = questions.length;
	questions[index] = question;
}

	
	



