/*

Author: Johnc
Proj No: 50181
Proj Name: Flash Construct 2.0
Usage:	Contains the methods for connecting and finding courseObjects and amending their properties such
				as quiz scores and tracking states.

Date: 10/02/06

*/



// Adds a courseObject to the .childObjsIndexed and .childObjsAssociative arrays
function _addChild(whatChildObj)
{
	this.debug("About to try and add a child obj:", 1, whatChildObj, false)
	var whatType = typeof whatChildObj
	var isCourseObject = (whatChildObj instanceof courseObject)
	if ((whatType == "object") && (isCourseObject))
	{
		// Check to make sure the parent object is not the same as the child
		// otherwise some nasty recursion problems could come up.
		if (whatChildObj != this.parentObj)
		{
			// If they don't exsist yet, create them.
			if (!this.childObjsIndexed)
			{
				this.childObjsIndexed = new Array()
				this.childObjsAssociative = new Array()
			}
			// Added both types as each form of reference can be useful.
			// Both should point to the same object.
			this.childObjsIndexed[this.childObjsIndexed.length] = whatChildObj;
			this.childObjsAssociative[whatChildObj.objID] = whatChildObj;
			//this.debug("Successfully added child obj:", 1, whatChildObj, false)
		}
		else
		{
			var debugArray = new Array()
			debugArray["this"] = this;
			debugArray["whatChildObj"] = whatChildObj;
			this.debug("Attempted to assign " + whatChildObj.objID + " as a child of " + this.objID + " however the parent is " + this.parentObj.objID + " and you cannot assign a child object that is the same as the parent.\n\n_addChild(), course_object_tracking_methods.js",3,debugArray,true)
		}
	}
	else
	{
		var debugArray = new Array()
		debugArray["this"] = this;
		debugArray["whatChildObj"] = whatChildObj;
		this.debug("Could not find a valid object for 'whatChildObj', child object not added. Value was:\n\n" + whatChildObj + "\n\n_addChild(), course_object_tracking_methods.js",3, debugArray, true)
	}
}


// If whatValue is set, the object will set its state to that
// then, if present, call its parent objects .upDateTracking()
// method so all tracking states are instantly updated.
//
// If no value is passed, the method checks the .trackingState
// of any child objects and updates itself according to them.
//
// Note, this means the setting a high lvl object's tracking state
// could be reset if the child objects tracking states don't match.
function _upDateTracking(whatValue)
{
	this.debug("_upDateTracking(whatValue: " + whatValue + ")", 1, this)
	// If there is a value then this should be a topic, set the value and ask the parent to update.
	if (whatValue)
	{
		this.debug("_upDateTracking():Setting '" + this.fullIDString + "' (" + this.objID + ") to : " + whatValue,1)
		if (parseInt(whatValue) > this.trackingState)
		{
			this.debug("_upDateTracking():Setting '" + this.fullIDString + "' (" + this.objID + ") to : " + whatValue,1)
			this.trackingState = whatValue;
			// As a topic has changed state, we should update the LMS, if needed.
			this.sendTrackingDataToLMS()
			this.commitLMS()
		}

		if (this.parentObj)
			this.parentObj.upDateTracking();
	}
	// If there is no value, then we have been called by a child,
	//loop through all children, update our tracking then call our parents upDateTracking() if we have one
	else if (this.childObjsIndexed)
	{
		var count = 0;
		var allPassed = true;	// If any are less than 2, then we aren't complete
		var oneStarted = false;	// If any are greater than one, then we are started
		var highestTrackingValue = 0; 	// For assessments, 3 or 4 can be passed, so we need to catch which.
		var assessmentTrackingValueFound = false;	// If any assessment topic is found, we want to use highestTrackingValue instead of 2 for the API_CORE.set_status()
		while (count < this.childObjsIndexed.length)
		{
			if (this.childObjsIndexed[count].objID.indexOf("exp")==-1)
			{
				this.debug("_upDateTracking(), this.childObjsIndexed[count].trackingState: " + this.childObjsIndexed[count].trackingState + ", this.childObjsIndexed[count].objID: " + this.childObjsIndexed[count].objID + ", this.childObjsIndexed[count].objType: " + this.childObjsIndexed[count].objType,1)
				if (this.childObjsIndexed[count].trackingState < 2)
				{
					allPassed = false;
				}

				if (highestTrackingValue < this.childObjsIndexed[count].trackingState)
				{
					this.debug("_upDateTracking(), increasing highestTrackingValue to: " + this.childObjsIndexed[count].trackingState,1)
					highestTrackingValue = this.childObjsIndexed[count].trackingState
				}

				if (this.childObjsIndexed[count].trackingState > 0)
				{
					oneStarted = true;
				}

				if (highestTrackingValue > 2)
				{
					assessmentTrackingValueFound = true;
				}

			}

			count++;
		}

		if (allPassed)
		{
			this.trackingState = highestTrackingValue;
		}
		else if (oneStarted)
		{
			this.trackingState = 1;
		}

		if (this.parentObj)
			this.parentObj.upDateTracking();
		// If your the course, you may need to setLessonStatus.
		if ((!this.parentObj) && (this.trackingState >= 2))
		{
			if (!assessmentTrackingValueFound)
			{
				this.debug("About to call 'API_CORE.set_status(2)'",1)
				API_CORE.set_status(2)
			}
			else
			{
				this.debug("About to call 'API_CORE.set_status()', highestTrackingValue: " + highestTrackingValue,1)
				API_CORE.set_status(highestTrackingValue)
			}
		}
	}
}

function _setFinalScore(whatScore)
{
	this.debug("_setFinalScore(whatScore: " + whatScore + "), this.objID: " + this.objID, 1, this, false)
	if (this.parentObj)
	{
		this.parentObj.setFinalScore(whatScore)
		return;
	}
	this.assessmentPercentage = whatScore;
	API_CORE.set_score(whatScore);
}

// Sets the this.objDescription based on the text passed. Called from the coursestructures.js.
function _setDescription(whatDescriptionText)
{
	this.objDescription = whatDescriptionText;
}

// Sets the this.objTranscript based on the text passed. Called from the coursestructures.js.
function _setTranscript(whatTranscriptText)
{
	this.objTranscript = whatTranscriptText;
}

function _setTime(whatTime)
{
	this.timeAllowed = whatTime;
}

function _setScreenRandomisation(whatState)
{
	this.randomiseQuestions = whatState;
}

/*

Depreciated function, page scores are now handled by the pageTrackingObject(), page_tracking_object.js

// Takes a screen ID and a 0 or 1 depending on wether the user passed or not.
// Places the scores in an associative array named diagnosticScreenScoresArray for diagnostic feedback.
function _addPageScore(whatScreenID, whatScore)
{
	if (!this.diagnosticScreenScoresArray)
		this.diagnosticScreenScoresArray = new Array();

	this.diagnosticScreenScoresArray[whatScreenID] = whatScore;
}
*/

// Called by diagnosticScoreTracking.js when the user fails a given screen.
// Extend functionality as required on a project by project basis.
function _loseLife()
{
	this.debug("Lost a life... fading fast.... I see a tunnel... etc.", 1, this, true);
	if (this.useLives)
	{
		this.currNumberOfLives--;
		if (this.currNumberOfLives <= 0)
		{
			alert("The user has lost all their lives, please extend the functionality as desired from _loseLife(), course_object_tracking_methods.js")
		}
	}
}

// Designed to start with currCourse and recurse down trying to match each layer
// with the current portion of the whatID split. If it fails to find an object,
// it return false after alerting the point of failure and the last good obect found.
function _findObject(whatID)
{
	this.debug("_findObject(whatID: " + whatID + ")",1)
	var foundNew = false;
	// Always start with the current course object.
	var currObj = currCourse;


	if ((whatID.indexOf("ppt") == -1) && (whatID.indexOf("pdf") == -1))
	{
		// If present and we aren't a ppt or pdf, remove the currCourse obj's ID as that is the highest level.
		whatID = whatID.replace(currObj.objID + "_","");
	}

	// Break the remaining ID into parts to loop through.
	var whatIDSplit = whatID.split("_");
	var count = 0;

	// If the ID is an exact match to the course object, return that,
	// otherwise continue through the children.
	if (currObj.objID == whatID)
		return currObj;


	this.debug("whatID after initial processing: " + whatID,1)


	// Loop through all the ID parts, this allows as many levels
	// as might be required.
	while (count < whatIDSplit.length)
	{
		// Check to see if we have a ppt or a pdf, if so, concatenate the remainder
		// of the ID split as the name will most likely have a number of extra _'s
		// that would throw of the find attempt.
		if ((whatIDSplit[count].indexOf("ppt") != -1) || (whatIDSplit[count].indexOf("pdf") != -1))
		{
			// Start from the current position + 1 to avoid adding the current entry twice.
			var iCount = count + 1;
			while (iCount < whatIDSplit.length)
			{
				whatIDSplit[count] = whatIDSplit[count] + "_" + whatIDSplit[iCount];
				iCount++;
			}
			this.debug("whatID after secondary processing: " + whatID,1)
		}

		// If its a match, set currObj.
		if (currObj.childObjsAssociative[whatIDSplit[count]])
		{
			// Change the currObj to equal the matching child.
			currObj = currObj.childObjsAssociative[whatIDSplit[count]];
			foundNew = true;
		}

		count++;
	}
	if (!foundNew)
	{
		this.debug("Failed to find object.\nwhatID: " + whatID + "\nFailed on portion: " + whatIDSplit[count] + "\nLast good object's ID: " + currObj.objID + "\n\n_findObject(), course_object_tracking_methods.js",3, currObj)
		return false;
	}

	//currObj.alertAll();
	return currObj;
}

// Calculates how many objects deep by working up the chain until
// it finds an object with no parents.
function _getDepth()
{
	//alert(this.objID)
	var currObj = this;
	var count = 0;
	while (currObj.parentObj)
	{
		currObj = currObj.parentObj;
		count++;
	}
	return count;
}

// Returns the objects tracking state as "not attempted" "incomplete" "completed"
function _getTrackingStateInEnglish()
{
	switch (this.trackingState)
	{
		case 0:
			return "Not attempted";
		break;
		case 1:
			return "Incomplete";
		break;
		case 2:
		case 3:	// As we don't identify passed and failed in
		case 4:	// the menu, just treat them as completed.
			return "Completed";
		break;
		default:
			alert("Unknown tracking state of " + this.trackingState + " found for " + this.fullIDString + " in _getTrackingStateInEnglish(), course_object_tracking_methods.js");
			return false;
		break;
	}
}

function _addMediaType(whatMediaType)
{
	if (!this.mediaTypes)
		this.mediaTypes = new Array();
	this.mediaTypes[whatMediaType] = true;
}
