/*

The score/tracking is set as a seperate object to ease serialization/deserialization for the suspend data.

The pageFormRecord is populated from question_screen.js

*/

function _updatePageFormRecord(whatPageID, whatFormID, whatValue)
{
	this.debug("updatePageFormRecord(whatPageID: " + whatPageID + ", whatFormID:" + whatFormID + ", whatValue:" + whatValue + ")" , 1)
	var pageState = this.getPageState(whatPageID)

	this.debug("updatePageFormRecord::pageState: " + pageState, 1)
	if (pageState < 2)
	{
		if (this.pageFormRecord[whatPageID])
		{
			this.debug("updatePageFormRecord(), updated state.", 1)
			this.pageFormRecord[whatPageID][whatFormID] = whatValue;
		}
		else
		{
			this.debug("updatePageFormRecord(), created new entry.", 1)
			this.pageFormRecord[whatPageID] = new Array()
			this.pageFormRecord[whatPageID][whatFormID] = whatValue;
		}
	}
	else
	{
		//his.debug("updatePageFormRecord(), NOT updated due to the page already being submited.", 2, false, false)
	}
	//this.pageFormRecord[whatPageID]
}

function _getPageFormRecord(whatPageID)
{
	this.debug("getPageFormRecord(whatPageID: " + whatPageID + ")", 1)
	if (this.pageFormRecord[whatPageID])
	{
		this.debug("getPageFormRecord(), returning form data.", 1)
		return this.pageFormRecord[whatPageID];
	}
	else
	{
		this.debug("getPageFormRecord(), no existing form data found.", 1, false, false)
		return false;
	}
}

function _checkFormRecordsForUnansweredOptions()
{
	this.debug("checkFormRecordsForUnansweredOptions()",1)
	for (var currPageId in this.pageQuestionTypes)
	{
		this.debug("checkFormRecordsForUnansweredOptions(), checking: " + currPageId, 1, this)
		if (this.checkPageFormRecordForUnansweredOptions(currPageId))
		{
			this.debug("checkFormRecordsForUnansweredOptions(), unanswered questions found in: " + currPageId, 1, this)
			return true;
		}
		else
		{
			this.debug("checkFormRecordsForUnansweredOptions(), all questions answered in: " + currPageId, 1, this)
		}
	}
	return false;
}

function _checkPageFormRecordForUnansweredOptions(whatPageID)
{
	this.debug("checkPageFormRecordForUnansweredOptions(whatPageID: " + whatPageID + ")", 1)
	var foundUnanswered = false;
	if (this.pageQuestionTypes[whatPageID])
	{
		this.debug("checkPageFormRecordForUnansweredOptions(), checking form data.", 1)
		var currIDList = this.pageQuestionTypes[whatPageID]
		for (var currQNBankID in currIDList)
		{
			switch (currIDList[currQNBankID])
			{
				case "Advanced SFL":
				case "MCQ":
				case "SFL":
					foundUnanswered = this.checkRadioUnanswered(whatPageID, currQNBankID)
				break;
				case "Drop down":
					foundUnanswered = this.checkDropDownUnanswered(whatPageID, currQNBankID)
				break;
				case "Open Input":
					foundUnanswered = this.checkOpenInputUnanswered(whatPageID, currQNBankID)
				break;
				default:
					this.debug("submitAll()::ERROR: An attempt to submit the screen: " + currScreenID + " was made, however the bank '" + currBankID + "' has a question type of " + this.pageQuestionTypes[currScreenID] + " and I've no idea how to deal with one of them.",3,this,true)
				break;
			}
			if (foundUnanswered)
			{
				this.debug("checkPageFormRecordForUnansweredOptions(), unanswered question: " + currQNBankID, 2, this)
				return true;
			}
		}

		//return this.pageFormRecord[whatPageID];
	}
	else
	{
		this.debug("checkPageFormRecordForUnansweredOptions(), no existing form data found, returning true as all must be unanswered.", 1, false, false)
		return true;
	}
	return false;
}

// Checks through the relivant form options and return true if none of them have been selected.
function _checkRadioUnanswered(whatPageID, whatQNBankID)
{
	this.debug("checkRadioUnanswered(whatPageID: " + whatPageID + ", whatQNBankID: " + whatQNBankID + ")", 1)
	var currFormArray = this.getPageFormRecord(whatPageID)
	for (var currFormID in currFormArray)
	{
		this.debug("checkRadioUnanswered(), currFormArray[" + currFormArray + "]: " + currFormArray[currFormID], 1)
		if (currFormID.indexOf(whatQNBankID) != -1)
		{
			if (currFormArray[currFormID].indexOf("true") != -1)
			{
				return false;
			}
		}
	}
	return true;
}


function _checkTextUnanswered(whatPageID, whatQNBankID)
{
	var currFormArray = this.getPageFormRecord(whatPageID)
	for (var currFormID in currFormArray)
	{
		if (currFormID.indexOf(whatQNBankID) != -1)
		{
			var currFormValue = currFormArray[currFormID].split("::")[0]
			if (currFormValue != "")
			{
				return false;
			}
		}
	}
	return true;
}


function _checkDropDownUnanswered(whatPageID, whatQNBankID)
{
	var currFormArray = this.getPageFormRecord(whatPageID)
	for (var currFormID in currFormArray)
	{
		if (currFormID.indexOf(whatQNBankID) != -1)
		{
			var currFormValue = currFormArray[currFormID].split("::")[0]
			if ((currFormValue != "0") && (currFormValue != "-1"))
			{
				return false;
			}
		}
	}
	return true;
}



function _updatePageState(whatPageID, whatState)
{
	this.debug("updatePageState(whatPageID: " + whatPageID + ", whatState:" + whatState + ")", 1)
	if (this.pageStateRecord[whatPageID])
	{
		if (this.pageStateRecord[whatPageID] < whatState)
		{
			this.debug("updatePageState(), updated state.", 1)
			this.pageStateRecord[whatPageID] = whatState
		}
	}
	else
	{
		this.debug("updatePageState(), created new entry.", 1)
		this.pageStateRecord[whatPageID] = whatState
	}
}

function _getPageState(whatPageID)
{
	// Commented out as this function gets called a LOT.
	// this.debug("getPageState(whatPageID: " + whatPageID + ")", 1)
	if (this.pageStateRecord[whatPageID])
	{
		return this.pageStateRecord[whatPageID]
	}
	else
	{
		return 0;
	}
}

function _updatePageScore(whatPageID, whatQNBankID, whatScore)
{
	this.debug("updatePageScore(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatScore:" + whatScore + ")", 1)
	if (!this.pageScore[whatPageID])
	{
		this.debug("updatePageScore(), created array for " + whatPageID, 1)
		this.pageScore[whatPageID] = new Array()
	}

	if (this.pageScore[whatPageID][whatQNBankID])
	{
		this.debug("updatePageScore(), updated state.", 1)
		this.pageScore[whatPageID][whatQNBankID] = whatScore
	}
	else
	{
		this.debug("updatePageScore(), created new entry.", 1)
		this.pageScore[whatPageID][whatQNBankID] = whatScore
	}
	this.updateTotalScore()
}

function _getPageScore(whatPageID, whatQNBankID)
{
	this.debug("getPageScore(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageScore[whatPageID][whatQNBankID])
	{
		return this.pageScore[whatPageID][whatQNBankID]
	}
	else
	{
		return 0;
	}
}

function _updatePageMaxScore(whatPageID, whatQNBankID, whatMaxScore)
{
	this.debug("updatePageMaxScore(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatMaxScore:" + whatMaxScore + ")", 1)
	if (!this.pageMaxScore[whatPageID])
	{
		this.debug("updatePageMaxScore(), created array for " + whatPageID, 1)
		this.pageMaxScore[whatPageID] = new Array()
	}

	if (this.pageMaxScore[whatPageID][whatQNBankID])
	{
		this.debug("updatePageMaxScore(), updated state.", 1)
		this.pageMaxScore[whatPageID][whatQNBankID] = whatMaxScore
	}
	else
	{
		this.debug("updateMaxPageScore(), created new entry.", 1)
		this.pageMaxScore[whatPageID][whatQNBankID] = whatMaxScore
	}
	this.updateTotalMaxScore()
}

function _getPageMaxScore(whatPageID, whatQNBankID)
{
	this.debug("getPageMaxScore(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageMaxScore[whatPageID][whatQNBankID])
	{
		return this.pageMaxScore[whatPageID][whatQNBankID]
	}
	else
	{
		this.debug("getPageMaxScore(), no max score was set.", 3)
		return 0;
	}
}

function _updateTotalMaxScore()
{
	this.debug("updatePageMaxScore()", 1)
	this.maxTotalScore = 0
	for (var currPage in this.pageMaxScore)
	{
		for (var currQuestion in this.pageMaxScore[currPage])
		{
			this.maxTotalScore += parseInt(this.pageMaxScore[currPage][currQuestion])
		}
	}
}

function _getTotalMaxScore()
{
	this.debug("getPageMaxScore()", 1)
	return this.maxTotalScore;
}

function _updateTotalScore()
{
	this.debug("updateTotalScore()", 1)
	this.totalScore = 0
	for (var currPage in this.pageMaxScore)
	{
		for (var currQuestion in this.pageScore[currPage])
		{
			this.totalScore += parseInt(this.pageScore[currPage][currQuestion])
		}
	}
}

function _getTotalScore()
{
	this.debug("getTotalScore()", 1)
	return this.totalScore;
}

function _updateQuestionText(whatPageID, whatQNBankID, whatQuestionText)
{
	this.debug("updateQuestionText(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatQuestionText:" + whatQuestionText + ")", 1);
	if (!this.pageQuestions[whatPageID])
	{
		this.debug("updateQuestionText(), created array for " + whatPageID, 1);
		this.pageQuestions[whatPageID] = new Array();
	}

	if (this.pageQuestions[whatPageID][whatQNBankID])
	{
		this.debug("updateQuestionText(), updated state.", 1);
		this.pageQuestions[whatPageID][whatQNBankID] = whatQuestionText;
	}
	else
	{
		this.debug("updateQuestionText(), created new entry.", 1);
		this.pageQuestions[whatPageID][whatQNBankID] = whatQuestionText;
	}
}

function _getQuestionText(whatPageID, whatQNBankID)
{
	this.debug("getQuestionText(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageQuestions[whatPageID][whatQNBankID])
	{
		return this.pageQuestions[whatPageID][whatQNBankID];
	}
	else
	{
		return 0;
	}
}

function _updateQuestionInstruction(whatPageID, whatQNBankID, whatQuestionInstruction)
{
	this.debug("updateQuestionInstruction(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatQuestionInstruction:" + whatQuestionInstruction + ")", 1);
	if (!this.pageQuestionInstructions[whatPageID])
	{
		this.debug("updateQuestionInstruction(), created array for " + whatPageID, 1);
		this.pageQuestionInstructions[whatPageID] = new Array();
	}

	if (this.pageQuestions[whatPageID][whatQNBankID])
	{
		this.debug("updateQuestionInstruction(), updated state.", 1);
		this.pageQuestionInstructions[whatPageID][whatQNBankID] = whatQuestionInstruction;
	}
	else
	{
		this.debug("updateQuestionInstruction(), created new entry.", 1);
		this.pageQuestionInstructions[whatPageID][whatQNBankID] = whatQuestionInstruction;
	}
}

function _getQuestionInstruction(whatPageID, whatQNBankID)
{
	this.debug("_getQuestionInstruction(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageQuestionInstructions[whatPageID][whatQNBankID])
	{
		return this.pageQuestionInstructions[whatPageID][whatQNBankID];
	}
	else
	{
		return 0;
	}
}

function _updateQuestionType(whatPageID, whatQNBankID, whatQuestionType)
{
	this.debug("updateQuestionType(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatQuestionType:" + whatQuestionType + ")", 1);
	if (!this.pageQuestionTypes[whatPageID])
	{
		this.debug("updateQuestionType(), created array for " + whatPageID, 1);
		this.pageQuestionTypes[whatPageID] = new Array();
	}

	if (this.pageQuestions[whatPageID][whatQNBankID])
	{
		this.debug("updateQuestionType(), updated state.", 1);
		this.pageQuestionTypes[whatPageID][whatQNBankID] = whatQuestionType;
	}
	else
	{
		this.debug("updateQuestionType(), created new entry.", 1);
		this.pageQuestionTypes[whatPageID][whatQNBankID] = whatQuestionType;
	}
}

function _getQuestionType(whatPageID, whatQNBankID)
{
	this.debug("getQuestionType(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageQuestionTypes[whatPageID][whatQNBankID])
	{
		return this.pageQuestionTypes[whatPageID][whatQNBankID];
	}
	else
	{
		return 0;
	}
}

function _updateQuestionFeedback(whatPageID, whatQNBankID, whatQuestionFeedback)
{
	this.debug("updateQuestionFeedback(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatQuestionFeedback:" + whatQuestionFeedback + ")", 1);
	if (!this.pageFeedbacks[whatPageID])
	{
		this.debug("updateQuestionFeedback(), created array for " + whatPageID, 1);
		this.pageFeedbacks[whatPageID] = new Array();
	}

	if (this.pageFeedbacks[whatPageID][whatQNBankID])
	{
		this.debug("updateQuestionFeedback(), updated state.", 1);
		this.pageFeedbacks[whatPageID][whatQNBankID] = whatQuestionFeedback;
	}
	else
	{
		this.debug("updateQuestionFeedback(), created new entry.", 1);
		this.pageFeedbacks[whatPageID][whatQNBankID] = whatQuestionFeedback;
	}
}

function _getQuestionFeedback(whatPageID, whatQNBankID)
{
	this.debug("getQuestionFeedback(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageFeedbacks[whatPageID][whatQNBankID])
	{
		return this.pageFeedbacks[whatPageID][whatQNBankID];
	}
	else
	{
		return 0;
	}
}

function _updateQuestionOptions(whatPageID, whatQNBankID, whatQuestionOptionsArray)
{
	this.debug("updateQuestionOptions(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatQuestionOptionsArray:" + whatQuestionOptionsArray + ")", 1);
	if (!this.pageOptions[whatPageID])
	{
		this.debug("updateQuestionOptions(), created array for " + whatPageID, 1);
		this.pageOptions[whatPageID] = new Array();
	}

	if (this.pageOptions[whatPageID][whatQNBankID])
	{
		this.debug("updateQuestionOptions(), updated state.", 1);
		this.pageOptions[whatPageID][whatQNBankID] = whatQuestionOptionsArray;
	}
	else
	{
		this.debug("updateQuestionOptions(), created new entry.", 1);
		this.pageOptions[whatPageID][whatQNBankID] = whatQuestionOptionsArray;
	}
}

function _getQuestionOptions(whatPageID, whatQNBankID)
{
	this.debug("getQuestionOptions(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageOptions[whatPageID][whatQNBankID])
	{
		return this.pageOptions[whatPageID][whatQNBankID];
	}
	else
	{
		return 0;
	}
}

function _updateQuestionCorrectAnswers(whatPageID, whatQNBankID, whatQuestionAnswers)
{
	this.debug("updateQuestionCorrectAnswers(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ", whatQuestionAnswers:" + whatQuestionAnswers + ")", 1);
	if (!this.pageCorrectAnswers[whatPageID])
	{
		this.debug("updateQuestionCorrectAnswers(), created array for " + whatPageID, 1);
		this.pageCorrectAnswers[whatPageID] = new Array();
	}

	if (this.pageCorrectAnswers[whatPageID][whatQNBankID])
	{
		this.debug("updateQuestionCorrectAnswers(), updated state.", 1);
		this.pageCorrectAnswers[whatPageID][whatQNBankID] = whatQuestionAnswers;
	}
	else
	{
		this.debug("updateQuestionCorrectAnswers(), created new entry.", 1);
		this.pageCorrectAnswers[whatPageID][whatQNBankID] = whatQuestionAnswers;
	}
}

function _getQuestionCorrectAnswers(whatPageID, whatQNBankID)
{
	this.debug("getQuestionCorrectAnswers(whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID + ")", 1)
	if (this.pageCorrectAnswers[whatPageID][whatQNBankID])
	{
		return this.pageCorrectAnswers[whatPageID][whatQNBankID];
	}
	else
	{
		this.debug("getQuestionCorrectAnswers(), no entry found for whatPageID: " + whatPageID + ", whatQNBankID:" + whatQNBankID, 3)
		return 0;
	}
}

function _submitAll()
{
	this.debug("submitAll()", 1)
	var result = true;
	if (this.checkFormRecordsForUnansweredOptions())
	{
		result = window.confirm("Are you sure you want to submit all your answers?\n\nSome questions are unanswered and will therefore be marked as incorrect.")
	}
	if (result)
	{
		// Loop through the parent object's page array looking for unsubmitted question screen's
		for (var currPage in this.parentObj.pageArray)
		{
			if (this.parentObj.pageArray[currPage][3] == "screenQuestion")
			{
				var currScreenID = this.parentObj.pageArray[currPage][0].slice(0, this.parentObj.pageArray[currPage][0].lastIndexOf(".htm"))
				this.submitScreen(currScreenID)
			}
		}
	}
}

function _submitScreen(currScreenID)
{
	this.debug("_submitScreen(currScreenID: " + currScreenID + ")", 1)
	if (!this.pageScore[currScreenID])
	{
		// Check to make sure there is a record of answers for that page.
		if (!this.pageCorrectAnswers[currScreenID])
		{
			this.debug("submitAll()::ERROR: An attempt to submit the screen: " + currScreenID + " was made, however this page does not appear to have been visited, so cannot be submited.",3,this,true)
		}
		// For the current page in the .pageCorrectAnswers array, start marking the bank questions
		for (var currBankID in this.pageCorrectAnswers[currScreenID])
		{
			this.debug("About to score bank: " + currBankID + ", type: " + this.pageQuestionTypes[currScreenID][currBankID], 1)
			switch (this.pageQuestionTypes[currScreenID][currBankID])
			{
				case "Drop down":
					var score = this.scoreDropDown(currScreenID, currBankID);
				break;
				case "Advanced SFL":
					var score = this.scoreAdvancedSFL(currScreenID, currBankID);
				break;
				case "SFL":
					var score = this.scoreSFL(currScreenID, currBankID);
				break;
				case "Open Input":
					var score = this.scoreOpenInput(currScreenID, currBankID);
				break;
				case "MCQ":
					var score = this.scoreMCQ(currScreenID, currBankID);
				break;
				default:
					this.debug("submitAll()::ERROR: An attempt to submit the screen: " + currScreenID + " was made, however the bank '" + currBankID + "' has a question type of " + this.pageQuestionTypes[currScreenID] + " and I've no idea how to deal with one of them.",3,this,true)
				break;
			}
			this.updatePageScore(currScreenID, currBankID, score);
		}
		this.updatePageState(currScreenID, 2);
	}
}

function _scoreDropDown(currScreenID, currBankID)
{
	var currBankAnswers = this.pageCorrectAnswers[currScreenID][currBankID]
	var optionCount = 1;
	var score = 0;

	for (var currBankQuestionOption in currBankAnswers)
	{
		var currFormID = "qn_" + currBankID + "_Option" + optionCount + "ID";
		var currOptionState = this.pageFormRecord[currScreenID][currFormID].split("::")[0];
		if (currOptionState == currBankAnswers[currBankQuestionOption])
		{
			score++
		}
		optionCount++;
	}
	return score;
}

function _scoreAdvancedSFL(currScreenID, currBankID)
{
	this.debug("scoreAdvancedSFL(currScreenID: " + currScreenID + ", currBankID: " + currBankID + ")", 1, this)
	var currBankAnswers = this.pageCorrectAnswers[currScreenID][currBankID]
	var optionCount = 1;
	var score = 0;

	for (var currOptionID in this.pageOptions[currScreenID][currBankID])
	{
		var optionID = this.getOptionID(this.pageOptions[currScreenID][currBankID][currOptionID])
		this.debug("optionID: " + optionID + ")", 1, this)
		if (this.pageFormRecord[currScreenID][optionID].split("::")[0] == "true")
			var currOptionState = true;
		else
			var currOptionState = false;

		if (currBankAnswers[currOptionID].toLowerCase() == "y")
		{
			if (currOptionState)
				score++;
		}
		else
		{
			if (currOptionState)
				score--;
		}

		optionCount++;
	}
	if (score < 0)
		score = 0;
	return score;
}

// Strips out the QN ID if present, otherwise returns false.
function _getOptionID(whatOptionString)
{
	this.debug("_getOptionID(whatOptionString: " + formID + ")",1)
	var regExpObj = /<input id="(\S+)" /g
	var formID = regExpObj.exec(whatOptionString)[1]
	var formCheckRegExp = /qn_\w+_\w+_Option\d+ID/g
	var formIDMatch = formID.match(formCheckRegExp)
	this.debug()
	if ((formID) && (formIDMatch))
	{
		this.debug("Reg exp found: " + formID,1)
		return formID;
	}
	else
	{
		this.debug("Failed to find ID in getOptionID(). formID: " + formID + ", formIDMatch: " + formIDMatch + ", whatOptionString: " + whatOptionString,3)
		return false;
	}

}

function _scoreSFL(currScreenID, currBankID)
{
	var currBankAnswers = this.pageCorrectAnswers[currScreenID][currBankID]
	var optionCount = 1;
	var score = 0;

	for (var currBankQuestionOption in currBankAnswers)
	{
		var currFormID = "qn_" + currBankID + "_Option" + optionCount + "ID";
		if (this.pageFormRecord[currScreenID][currFormID].split("::")[0] == "true")
			var currOptionState = true;
		else
			var currOptionState = false;

		if (currBankAnswers[currBankQuestionOption].toLowerCase() == "y")
		{
			if (currOptionState)
				score++;
		}
		else
		{
			if (currOptionState)
				score--;
		}

		optionCount++;
	}

	if (score < 0)
		score = 0;
	return score;
}

function _scoreMCQ(currScreenID, currBankID)
{
	var currBankAnswer = this.pageCorrectAnswers[currScreenID][currBankID]
	var optionCount = 1;
	var score = 0;
	var currFormID = "qn_" + currBankID + "_Option" + currBankAnswer + "ID";
	if (this.pageFormRecord[currScreenID][currFormID].split("::")[0] == "true")
	{
		score++;
	}

	return score;
}

function _scoreOpenInput(currScreenID, currBankID)
{
	this.debug("_scoreOpenInput(currScreenID: " + currScreenID + ", currBankID: " + currBankID + ")",1)
	var currBankAnswers = this.pageCorrectAnswers[currScreenID][currBankID]
	var optionCount = 1;
	var score = 0;

	for (var currBankQuestionOption in currBankAnswers)
	{
		var currAnswersArray = currBankAnswers[currBankQuestionOption].split("::");
		this.debug("currAnswersArray: ", 1, currAnswersArray)
		var currFormID = "qn_" + currBankID + "_Option" + optionCount + "ID";
		this.debug("this.pageFormRecord[currScreenID][currFormID].split('::')[0]: " + this.pageFormRecord[currScreenID][currFormID].split("::")[0],1)
		var userAnswer = this.pageFormRecord[currScreenID][currFormID].split("::")[0]
		var isCorrect = false;
		for (var currAnswer in currAnswersArray)
		{
			this.debug("userAnswer: " + userAnswer + ", currAnswersArray: " + currAnswersArray,1)
			if (userAnswer == currAnswersArray[currAnswer])
			{
				isCorrect = true;
				break;
			}
		}
		if (isCorrect)
		{
			score++
		}
		optionCount++;
	}
	return score;
}

function _getQuestionAnswerBox(whatPage, whatQNBankID)
{
	if (this.pageQuestionTypes[whatPage])
	{
		switch (this.pageQuestionTypes[whatPage][whatQNBankID])
		{
			case "MCQ":
				var altText = this.getAnswerBoxMCQ(whatPage, whatQNBankID)
			break;
			case "Advanced SFL":
			case "SFL":
				var altText = this.getAnswerBoxSFL(whatPage, whatQNBankID)
			break;
			case "Drop down":
				var altText = this.getAnswerBoxDropDown(whatPage, whatQNBankID)
			break;
			case "Open Input":
				var altText = this.getAnswerBoxOpenInput(whatPage, whatQNBankID)
			break;
			default:
				this.debug("getQuestionAnswerBox()::ERROR: An attempt to create an answer box for the screen: " + whatPage + " was made, however the bank '" + whatQNBankID + "' has a question type of '" + this.pageQuestionTypes[whatPage][whatQNBankID] + "' and I've no idea how to deal with one of them.",3,this,true)
			break;
		}
		var boxText = "<img src='" + this.parentObj.rootPath + "images/answer_info.gif' alt='" + altText + "' />"
		return boxText
	}
	else
	{
		this.debug("getQuestionAnswerBox()::ERROR: The question type for " + whatPage + ", " + whatQNBankID + " was not found, please make sure a bank question of that ID exists or amend the screen question.",3)
		return "<span style='color:red;'>!! Bank not found. !!</span>";
	}
}

function _getAnswerBoxMCQ(whatPage, whatQNBankID)
{
	var altText = "Answer:\n" + this.pageCorrectAnswers[whatPage][whatQNBankID]
	return altText;
}

function _getAnswerBoxSFL(whatPage, whatQNBankID)
{
	this.debug("getAnswerBoxSFL(whatPage: " + whatPage + ", whatQNBankID: " + whatQNBankID + ")", 1, this)
	var altText = "Answers:\n"
	for (var currAnswer in this.pageCorrectAnswers[whatPage][whatQNBankID])
	{
		if (this.pageCorrectAnswers[whatPage][whatQNBankID][currAnswer].toLowerCase() == "y")
			altText += (parseInt(currAnswer) + 1) + ": True\n";
		else
			altText += (parseInt(currAnswer) + 1) + ": False\n";
	}
	return altText;
}

function _getAnswerBoxDropDown(whatPage, whatQNBankID)
{
	var altText = "Answers:\n"

	this.debug("getAnswerBoxDropDown(whatPage: " + whatPage + ", whatQNBankID: " + whatQNBankID + ")", 1, this)
	for (var currAnswer in this.pageCorrectAnswers[whatPage][whatQNBankID])
	{
		altText += "Dropdown " + (parseInt(currAnswer) + 1) + ": " + this.pageCorrectAnswers[whatPage][whatQNBankID][currAnswer] + "\n";
	}
	return altText;
}

function _getAnswerBoxOpenInput(whatPage, whatQNBankID)
{
	var altText = "Answers:\n"
	for (var currAnswer in this.pageCorrectAnswers[whatPage][whatQNBankID])
	{
		altText += "Input " + (parseInt(currAnswer) + 1) + ": " + this.pageCorrectAnswers[whatPage][whatQNBankID][currAnswer].replace(/\|\|/gi, " or ") + "\n";
	}
	return altText;
}

function _updateMiscData(whatPage, whatQNBankID, whatData)
{
	switch (whatData["questionType"])
	{
		case "MCQ":
		case "SFL":
		case "Drop down":
		case "Open Input":
			// No misc data on these screen types
		break;
		case "Advanced SFL":
			this.updateAdvancedSFLMiscData(whatPage, whatQNBankID, whatData)
		break;
		default:
			this.debug("_updateMiscData()::ERROR: An attempt to add misc data to the screen: " + whatPage + " was made, however the bank '" + whatQNBankID + "' has a question type of '" + this.pageQuestionTypes[whatPage][whatQNBankID] + "' and I've no idea how to deal with one of them.",3,this,true)
		break;
	}
}

function _updateAdvancedSFLMiscData(whatPageID, whatQNBankID, whatData)
{
		this.debug("_updateAdvancedSFLMiscData(whatPageID: " + whatPageID + ", whatQNBankID: " + whatQNBankID + ", whatData: " + whatData + ")", 1)
	if (!this.numberOfCorrectOptionsToPick[whatPageID])
	{
		this.numberOfCorrectOptionsToPick[whatPageID] = new Array();
		this.numberOfWrongOptionsToPick[whatPageID] = new Array();
	}
	if (this.numberOfCorrectOptionsToPick[whatPageID][whatQNBankID])
	{
		this.numberOfCorrectOptionsToPick[whatPageID][whatQNBankID] = parseInt(whatData['cOptions']);
		this.numberOfWrongOptionsToPick[whatPageID][whatQNBankID] = parseInt(whatData['wOptions']);
		this.debug("_updateAdvancedSFLMiscData(), updated entry.", 1)
	}
	else
	{
		this.numberOfCorrectOptionsToPick[whatPageID][whatQNBankID] = parseInt(whatData['cOptions']);
		this.numberOfWrongOptionsToPick[whatPageID][whatQNBankID] = parseInt(whatData['wOptions']);
		this.debug("_updateAdvancedSFLMiscData(), created new entry.", 1)
	}
}

function _postProcessing(whatPageID, whatQNBankID, whatData)
{
	switch (this.pageQuestionTypes[whatPageID][whatQNBankID])
	{
		case "MCQ":
		break;
		case "SFL":
		break;
		case "Drop down":
		break;
		case "Open Input":
			// No post processing is as yet required on these screen types
		break;
		case "Advanced SFL":
			this.postProcessAdvancedSFL(whatPageID, whatQNBankID, whatData)
		break;
		default:
			this.debug("_postProcessing()::ERROR: An attempt to post process the screen: " + whatPageID + " was made, however the bank '" + whatQNBankID + "' has a question type of '" + this.pageQuestionTypes[whatPageID][whatQNBankID] + "' and I've no idea how to deal with one of them.",3,this,true)
		break;
	}

}

function _postProcessAdvancedSFL(whatPageID, whatQNBankID)
{
	this.debug("this.pageCorrectAnswers[whatPageID]:" + this.pageCorrectAnswers[whatPageID],1)
	// If its not a sub array, make it one.
	if (!this.correctOptionsArray[whatPageID])
	{
		this.correctOptionsArray[whatPageID] = new Array();
		this.wrongOptionsArray[whatPageID] = new Array();
	}
	// Then make another sub array for storing the bank specific answers in.
	if (!this.correctOptionsArray[whatPageID][whatQNBankID])
	{
		this.correctOptionsArray[whatPageID][whatQNBankID] = new Array();
		this.wrongOptionsArray[whatPageID][whatQNBankID] = new Array();
	}
	this.fillAdvancedSFLOptionsArray(whatPageID, whatQNBankID)
	this.rePopulateOptionsArray(whatPageID, whatQNBankID)
	this.rePopulateAnswersArray(whatPageID, whatQNBankID)
}


function _fillAdvancedSFLOptionsArray(whatPageID, whatQNBankID)
{
	var count = 0;
	this.debug("_fillAdvancedSFLOptionsArray(whatPageID: " + whatPageID + ", whatQNBankID: " + whatQNBankID + ")",1)
	while (count < this.pageOptions[whatPageID][whatQNBankID].length)
	{
		if (this.pageCorrectAnswers[whatPageID][whatQNBankID][count].toLowerCase() == "y")
		{
			this.debug("Added to correct array: " + this.pageOptions[whatPageID][whatQNBankID][count],1)
			this.correctOptionsArray[whatPageID][whatQNBankID][this.correctOptionsArray[whatPageID][whatQNBankID].length] = this.pageOptions[whatPageID][whatQNBankID][count]
		}
		else
		{
			this.debug("Added to wrong array: " + this.pageOptions[whatPageID][whatQNBankID][count],1)
			this.wrongOptionsArray[whatPageID][whatQNBankID][this.wrongOptionsArray[whatPageID][whatQNBankID].length] = this.pageOptions[whatPageID][whatQNBankID][count]
		}
		count++;
	}
}

function _rePopulateOptionsArray(whatPageID, whatQNBankID)
{
	this.pageOptions[whatPageID][whatQNBankID] = new Array();

	var totalToPick = this.numberOfCorrectOptionsToPick[whatPageID][whatQNBankID] + this.numberOfWrongOptionsToPick[whatPageID][whatQNBankID]
	while (this.pageOptions[whatPageID][whatQNBankID].length < totalToPick)
	{
		// If the array length hasn't exceeded the number of correct options we need to pick, and there are still some to pick,
		// grab another.
		if ((this.correctOptionsArray[whatPageID][whatQNBankID].length > 0) && (this.pageOptions[whatPageID][whatQNBankID].length < this.numberOfCorrectOptionsToPick[whatPageID][whatQNBankID]))
		{
			var currOptionToTakeIndex = this.getRandom(0, (this.correctOptionsArray[whatPageID][whatQNBankID].length - 1));
			this.pageOptions[whatPageID][whatQNBankID][this.pageOptions[whatPageID][whatQNBankID].length] = this.correctOptionsArray[whatPageID][whatQNBankID][currOptionToTakeIndex];
			// Used in _rePopulateAnswersArray() to re-create the answers array based on the new options, parsed out as part of that process.
			this.pageOptions[whatPageID][whatQNBankID][this.pageOptions[whatPageID][whatQNBankID].length - 1] += ":true:";
			this.correctOptionsArray[whatPageID][whatQNBankID] = this.removeElement(this.correctOptionsArray[whatPageID][whatQNBankID], currOptionToTakeIndex);

			this.debug("Added correct option: " + this.pageOptions[whatPageID][whatQNBankID][this.pageOptions[whatPageID][whatQNBankID].length - 1] + ", currOptionToTakeIndex: " + currOptionToTakeIndex + " from ", 1, this.correctOptionsArray[whatPageID][whatQNBankID])
		}
		else if (this.wrongOptionsArray[whatPageID][whatQNBankID].length > 0)
		{
			var currOptionToTakeIndex = this.getRandom(0, (this.wrongOptionsArray[whatPageID][whatQNBankID].length - 1));
			this.pageOptions[whatPageID][whatQNBankID][this.pageOptions[whatPageID][whatQNBankID].length] = this.wrongOptionsArray[whatPageID][whatQNBankID][currOptionToTakeIndex];
			// Used in _rePopulateAnswersArray() to re-create the answers array based on the new options, parsed out as part of that process.
			this.pageOptions[whatPageID][whatQNBankID][this.pageOptions[whatPageID][whatQNBankID].length - 1] += ":false:";
			this.wrongOptionsArray[whatPageID][whatQNBankID] = this.removeElement(this.wrongOptionsArray[whatPageID][whatQNBankID], currOptionToTakeIndex);
			this.debug("Added wrong option: " + this.pageOptions[whatPageID][whatQNBankID][this.pageOptions[whatPageID][whatQNBankID].length - 1] + ", currOptionToTakeIndex: " + currOptionToTakeIndex + " from ", 1, this.wrongOptionsArray[whatPageID][whatQNBankID])
		}


		// If the correct array is empty and we still don't have enough options in the new array, throw an error and stop the loop.
		if ((this.correctOptionsArray[whatPageID][whatQNBankID].length == 0) && (this.pageOptions[whatPageID][whatQNBankID].length < this.numberOfCorrectOptionsToPick[whatPageID][whatQNBankID]))
		{
			//this.parentObj.debug("Please provide options OR reduce the 'No. of correct options' for " + whatPageID + ", " + whatQNBankID, 1, this, false)
			break;
		}

		// Removed as some bank questions are turning up with only correct options.
		//if ((this.wrongOptionsArray[whatPageID][whatQNBankID].length == 0) && (this.pageOptions[whatPageID][whatQNBankID].length < totalToPick))
		//{
		//	this.parentObj.debug("Please provide options OR reduce the 'No. of wrong options' for " + whatPageID + ", " + whatQNBankID, 3, this, false)
		//	break;
		//}
	}
	//this.parentObj.debug("About to mix up the options: ",1,this.pageOptions[whatPageID][whatQNBankID])
	this.pageOptions[whatPageID][whatQNBankID] = this.pageOptions[whatPageID][whatQNBankID].sort(_randomSort)
	//this.parentObj.debug("Mixed up the options: ",1,this.pageOptions[whatPageID][whatQNBankID])
}

function _removeElement(whatArray, whatIndex)
{
	var returnArray = new Array()
	for (var currIndex in whatArray)
	{
		if (currIndex != whatIndex)
			returnArray[returnArray.length] = whatArray[currIndex]
	}
	return returnArray;
}

function _getRandom(minNum, maxNum)
{
	//this.parentObj.debug("_getRandom(minNum: " + minNum + ", maxNum: " + maxNum + ")",1)
	return minNum + Math.round((Math.random() * maxNum))
}

function _randomSort(a, b)
{
	var returnValue = Math.round(Math.random());
	return returnValue
}

function _rePopulateAnswersArray(whatPageID, whatQNBankID)
{
	//this.parentObj.debug("_rePopulateAnswersArray(whatPageID: " + whatPageID + ", whatQNBankID: " + whatQNBankID + ")",1)
	this.pageCorrectAnswers[whatPageID][whatQNBankID] = new Array();
	var count = 0;
	while (count < this.pageOptions[whatPageID][whatQNBankID].length)
	{
		if (this.pageOptions[whatPageID][whatQNBankID][count].indexOf(":false:") != -1)
		{
			this.pageOptions[whatPageID][whatQNBankID][count] = this.pageOptions[whatPageID][whatQNBankID][count].replace(":false:","")
			this.pageCorrectAnswers[whatPageID][whatQNBankID][this.pageCorrectAnswers[whatPageID][whatQNBankID].length] = "n"
		}
		else
		{
			this.pageOptions[whatPageID][whatQNBankID][count] = this.pageOptions[whatPageID][whatQNBankID][count].replace(":true:","")
			this.pageCorrectAnswers[whatPageID][whatQNBankID][this.pageCorrectAnswers[whatPageID][whatQNBankID].length] = "y"
		}
		count++;
	}
	//this.parentObj.debug("_rePopulateAnswersArray():this.pageCorrectAnswers[whatPageID][whatQNBankID]: ",1,this.pageCorrectAnswers[whatPageID][whatQNBankID])

}

function _addPageData(whatPage, whatQNBankID, whatDataType, whatData)
{
	this.debug("addPageData(whatPage: " + whatPage + ", whatQNBankID: " + whatQNBankID + ", whatDataType:" + whatDataType + ", whatData: " + whatData + ")", 1)
	// If we havn't post processed the data before.
	if ((!this.processedBanks[whatPage]) || (this.processedBanks[whatPage][whatQNBankID] < 3) || (!this.processedBanks[whatPage][whatQNBankID]))
	{
		if (!this.processedBanks[whatPage])
		{
			this.debug("addPageData():Creating page reference",1)
			this.processedBanks[whatPage] = new Array()
		}
		if (!this.processedBanks[whatPage][whatQNBankID])
		{
			this.processedBanks[whatPage][whatQNBankID] = 1;
			this.debug("addPageData():Created first data, count = " + this.processedBanks[whatPage][whatQNBankID],1)
		}
		else
		{
			this.processedBanks[whatPage][whatQNBankID]++;
			this.debug("addPageData():Adding more data, count = " + this.processedBanks[whatPage][whatQNBankID],1)
		}
		switch(whatDataType)
		{
			case "data1":
				this.debug("addPageData()::data1", 1, whatData, true)
				this.updatePageMaxScore(whatPage, whatQNBankID, whatData['maxScore'])
				this.updateQuestionText(whatPage, whatQNBankID, whatData['questionText'])
				this.updateQuestionInstruction(whatPage, whatQNBankID, whatData['questionInstruction'])
				this.updateQuestionType(whatPage, whatQNBankID, whatData['questionType'])
				this.updateQuestionOptions(whatPage, whatQNBankID, whatData['questionOptions'])
				this.updateMiscData(whatPage, whatQNBankID, whatData)
			break;
			case "data2":
				var key = "EpicTrackingDecoderRing123";																																																																																																																																																																																																eval("var k" + "ey = he" + "xTo" + "By" + "teArray('0000000f0000f00000f0000000000000')")
				var rawByteArray = hexToByteArray(whatData[0])
				var byteArray = rijndaelDecrypt(rawByteArray,key,'ECB')
				var evalText = byteArrayToString(byteArray)
				this.debug("addPageData()::data2:evalText:\n\n" + evalText, 1)
				eval(evalText)
				//this.pageAnswers[]
				this.updateQuestionCorrectAnswers(whatPage, whatQNBankID, qc)
			break;
			case "data3":
				this.debug("addPageData()::data3", 1, whatData, true)
				this.updateQuestionFeedback(whatPage, whatQNBankID, whatData['feedback'])
				// Now we have finished adding all the data, carry out any required post processing.
				this.postProcessing(whatPage, whatQNBankID, whatData)
			break;
			default:
				this.debug("addPageData(), Unknown whatDataType: " + whatDataType, 1)
			break;
		}
	}
}

function _debug(msg, priority, whatObj, showCallee)
{
	if (DEBUG)
		DEBUG.lert(msg, priority, whatObj, showCallee)
}

function pageTrackingObject(whatParent)
{
	this.debug("NEW pageTrackingObject()", 0);
	this.debug("pageTrackingObject(whatParent: " + whatParent + ")", 1, false, true);
	this.totalScore = 0;
	this.maxTotalScore = 0;
	this.percentAge = 0;
	this.parentObj = whatParent;
	this.pageFormRecord = new Array();
	this.pageStateRecord = new Array();
	this.pageQuestions = new Array();
	this.pageQuestionInstructions = new Array();
	this.pageQuestionTypes = new Array();
	this.pageOptions = new Array();
	this.pageCorrectAnswers = new Array();
	this.pageFeedbacks = new Array();
	this.pageScore = new Array();
	this.pageMaxScore = new Array();
	this.processedBanks = new Array();
	this.numberOfCorrectOptionsToPick = new Array();
	this.numberOfWrongOptionsToPick = new Array();
	this.correctOptionsArray = new Array();
	this.wrongOptionsArray = new Array();
	this.debug("Created pageTrackingObject()", 1, this, false);
}

pageTrackingObject.prototype.submitAll = _submitAll;
pageTrackingObject.prototype.submitScreen = _submitScreen;

pageTrackingObject.prototype.scoreDropDown = _scoreDropDown;
pageTrackingObject.prototype.scoreAdvancedSFL = _scoreAdvancedSFL;
pageTrackingObject.prototype.getOptionID = _getOptionID;
pageTrackingObject.prototype.scoreSFL = _scoreSFL;
pageTrackingObject.prototype.scoreMCQ = _scoreMCQ;
pageTrackingObject.prototype.scoreOpenInput = _scoreOpenInput;

pageTrackingObject.prototype.getQuestionAnswerBox = _getQuestionAnswerBox;
pageTrackingObject.prototype.getAnswerBoxMCQ = _getAnswerBoxMCQ;
pageTrackingObject.prototype.getAnswerBoxSFL = _getAnswerBoxSFL;
pageTrackingObject.prototype.getAnswerBoxDropDown = _getAnswerBoxDropDown;
pageTrackingObject.prototype.getAnswerBoxOpenInput = _getAnswerBoxOpenInput;

pageTrackingObject.prototype.updatePageFormRecord = _updatePageFormRecord;
pageTrackingObject.prototype.getPageFormRecord = _getPageFormRecord;


pageTrackingObject.prototype.checkFormRecordsForUnansweredOptions = _checkFormRecordsForUnansweredOptions;
pageTrackingObject.prototype.checkPageFormRecordForUnansweredOptions = _checkPageFormRecordForUnansweredOptions;
pageTrackingObject.prototype.checkRadioUnanswered = _checkRadioUnanswered;
pageTrackingObject.prototype.checkTextUnanswered = _checkTextUnanswered;
pageTrackingObject.prototype.checkDropDownUnanswered = _checkDropDownUnanswered;


pageTrackingObject.prototype.updatePageState = _updatePageState;
pageTrackingObject.prototype.getPageState = _getPageState;

pageTrackingObject.prototype.updatePageScore = _updatePageScore;
pageTrackingObject.prototype.getPageScore = _getPageScore;

pageTrackingObject.prototype.updatePageMaxScore = _updatePageMaxScore;
pageTrackingObject.prototype.getPageMaxScore = _getPageMaxScore;

pageTrackingObject.prototype.updateTotalScore = _updateTotalScore;
pageTrackingObject.prototype.getTotalScore = _getTotalScore;

pageTrackingObject.prototype.updateTotalMaxScore = _updateTotalMaxScore;
pageTrackingObject.prototype.getTotalMaxScore = _getTotalMaxScore;

pageTrackingObject.prototype.updateQuestionText = _updateQuestionText;
pageTrackingObject.prototype.getQuestionText = _getQuestionText;

pageTrackingObject.prototype.updateQuestionInstruction = _updateQuestionInstruction;
pageTrackingObject.prototype.getQuestionInstruction = _getQuestionInstruction;

pageTrackingObject.prototype.updateQuestionOptions = _updateQuestionOptions;
pageTrackingObject.prototype.getQuestionOptions = _getQuestionOptions;

pageTrackingObject.prototype.updateQuestionType = _updateQuestionType;
pageTrackingObject.prototype.getQuestionType = _getQuestionType;

pageTrackingObject.prototype.updateQuestionFeedback = _updateQuestionFeedback;
pageTrackingObject.prototype.getQuestionFeedback = _getQuestionFeedback;

pageTrackingObject.prototype.updateQuestionCorrectAnswers = _updateQuestionCorrectAnswers;
pageTrackingObject.prototype.getQuestionCorrectAnswers = _getQuestionCorrectAnswers;

pageTrackingObject.prototype.updateMiscData = _updateMiscData;
pageTrackingObject.prototype.updateAdvancedSFLMiscData = _updateAdvancedSFLMiscData;

pageTrackingObject.prototype.addPageData = _addPageData;

pageTrackingObject.prototype.postProcessing = _postProcessing;
pageTrackingObject.prototype.postProcessAdvancedSFL = _postProcessAdvancedSFL;
pageTrackingObject.prototype.fillAdvancedSFLOptionsArray = _fillAdvancedSFLOptionsArray;
pageTrackingObject.prototype.rePopulateOptionsArray = _rePopulateOptionsArray;

pageTrackingObject.prototype.removeElement = _removeElement;
pageTrackingObject.prototype.getRandom = _getRandom;

pageTrackingObject.prototype.rePopulateAnswersArray = _rePopulateAnswersArray;

pageTrackingObject.prototype.debug = _debug;
