/* Copyright © 2003-2005 Rustici Software, LLC  All Rights Reserved. */

var SCORM2004_LOGOUT = "logout";
var SCORM2004_SUSPEND = "suspend";
var SCORM2004_NORMAL_EXIT = "normal";
var SCORM2004_TIMEOUT = "time-out";

var SCORM2004_PASSED = "passed";
var SCORM2004_FAILED = "failed";
var SCORM2004_UNKNOWN = "unknown";

var SCORM2004_COMPLETED = "completed";
var SCORM2004_INCOMPLETE = "incomplete";
var SCORM2004_NOT_ATTEMPTED = "not attempted";

//var SCORM_BROWSED = "browsed";

var SCORM2004_CREDIT = "credit";
var SCORM2004_NO_CREDIT = "no-credit";

var SCORM2004_BROWSE = "browse";
var SCORM2004_NORMAL = "normal";
var SCORM2004_REVIEW = "review";

var SCORM2004_ENTRY_ABINITIO = "ab_initio";
var SCORM2004_ENTRY_RESUME = "resume";
var SCORM2004_ENTRY_NORMAL = "";

var SCORM2004_TLA_EXIT_MESSAGE = "exit,message";
var SCORM2004_TLA_EXIT_NO_MESSAGE = "exit,no message";
var SCORM2004_TLA_CONTINUE_MESSAGE = "continue,message";
var SCORM2004_TLA_CONTINUE_NO_MESSAGE = "continue,no message";


var SCORM2004_RESULT_CORRECT = "correct";
var SCORM2004_RESULT_WRONG = "incorrect";
var SCORM2004_RESULT_UNANTICIPATED = "unanticipated";
var SCORM2004_RESULT_NEUTRAL = "neutral";

var SCORM2004_INTERACTION_TYPE_TRUE_FALSE = "true-false";
var SCORM2004_INTERACTION_TYPE_CHOICE = "choice";
var SCORM2004_INTERACTION_FILL_IN = "fill-in";
var SCORM2004_INTERACTION_LONG_FILL_IN = "long-fill-in";
var SCORM2004_INTERACTION_TYPE_MATCHING = "matching";
var SCORM2004_INTERACTION_TYPE_PERFORMANCE = "performance";
var SCORM2004_INTERACTION_TYPE_SEQUENCING = "sequencing";
var SCORM2004_INTERACTION_TYPE_LIKERT = "likert";
var SCORM2004_INTERACTION_TYPE_NUMERIC = "numeric";


var SCORM2004_NO_ERROR = "0";
var SCORM2004_ERROR_INVALID_PREFERENCE = "-1";
var SCORM2004_ERROR_INVALID_STATUS = "-2";
var SCORM2004_ERROR_INVALID_SPEED = "-3";
var SCORM2004_ERROR_INVALID_TIMESPAN = "-4";
var SCORM2004_ERROR_INVALID_TIME_LIMIT_ACTION = "-5";
var SCORM2004_ERROR_INVALID_DECIMAL = "-6";
var SCORM2004_ERROR_INVALID_CREDIT = "-7";
var SCORM2004_ERROR_INVALID_LESSON_MODE = "-8";
var SCORM2004_ERROR_INVALID_ENTRY = "-9";

var SCORM2004_TRUE = "true";
var SCORM2004_FALSE = "false";




var intSCORM2004Error = SCORM2004_NO_ERROR;
var strSCORM2004ErrorString = "";
var strSCORM2004ErrorDiagnostic = "";

var SCORM2004_objAPI = null;



function SCORM2004_Initialize(){

	WriteToDebug("In SCORM2004_Initialize");

	var blnResult = true;
	
	SCORM2004_ClearErrorInfo();
	
	WriteToDebug("Grabbing API");
	
	try{
		SCORM2004_objAPI = SCORM2004_GrabAPI();
	}
	catch (e){
		WriteToDebug("Error grabbing 1.2 API-" + e.name + ":" + e.message);
	}
	
	if (typeof(SCORM2004_objAPI) == "undefined" || SCORM2004_objAPI == null){
		WriteToDebug("Unable to acquire SCORM API:")
		WriteToDebug("SCORM2004_objAPI=" + typeof(SCORM2004_objAPI));
		
		InitializeExecuted(false, "Error - unable to acquire LMS API, content may not play properly and results may not be recorded.  Please contact technical support.");
		return false;
	}
	
	WriteToDebug("Calling LMSInit");
	
	blnResult = SCORM2004_CallInitialize();
	
	if (! blnResult){
		WriteToDebug("ERROR Initializing LMS");		
			
		InitializeExecuted(false, "Error initializing communications with LMS");
		
		return false;	
	}
	
	

	//only set the status to incomplete if it's not attempted yet
	if (SCORM2004_GetStatus() == LESSON_STATUS_NOT_ATTEMPTED){
		WriteToDebug("Setting Status to Incomplete");
		blnResult = SCORM2004_CallSetValue("cmi.completion_status", SCORM2004_INCOMPLETE);
	}

	
	//we want to set the exit type to suspend immediately because some LMS's only store data if they get a suspend request
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.exit", SCORM2004_TranslateExitTypeToSCORM(DEFAULT_EXIT_TYPE));

	
	WriteToDebug("Calling InitializeExecuted with parameter-" + blnResult);
	
	InitializeExecuted(blnResult, "");
	
	return;
	
}




function SCORM2004_Finish(strExitType, blnStatusWasSet){

	WriteToDebug("In SCORM2004_Finish strExitType=" + strExitType + ", blnStatusWasSet=" + blnStatusWasSet);
	
	var strStatusAfterCompletion;
	var blnResult = true;
	
	SCORM2004_ClearErrorInfo();
	
	if ( (strExitType == EXIT_TYPE_FINISH) && ! blnStatusWasSet ){
		
		WriteToDebug("Getting completion status");
		
		strStatusAfterCompletion = SCORM2004_GetCompletionStatus();
		
		WriteToDebug("Setting completion status to " + strStatusAfterCompletion);
		
		blnResult = blnResult && SCORM2004_CallSetValue("cmi.completion_status", strStatusAfterCompletion);

	}
	
	WriteToDebug("Setting Exit");
	
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.exit", SCORM_TranslateExitTypeToSCORM(strExitType));
	
	WriteToDebug("Calling Commit");
	
	blnResult = blnResult && SCORM2004_CallCommit();
	
	WriteToDebug("Calling Finish");
	
	blnResult = blnResult && SCORM2004_CallTerminate();	
	
	WriteToDebug("Returning " + blnResult);
	
	return blnResult;

}


function SCORM2004_CommitData(){

	WriteToDebug("In SCORM2004_CommitData");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallCommit();

}



//---------------------------------------------------------------------------------
//General Get and Set Values

function SCORM2004_GetStudentID(){	

	WriteToDebug("In SCORM2004_GetStudentID");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallGetValue("cmi.learner_id");

}

function SCORM2004_GetStudentName(){

	WriteToDebug("In SCORM2004_GetStudentName");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallGetValue("cmi.learner_name");

}

function SCORM2004_GetBookmark(){
	WriteToDebug("In SCORM2004_GetBookmark");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallGetValue("cmi.location");

}

function SCORM2004_SetBookmark(strBookmark){
	WriteToDebug("In SCORM2004_SetBookmark strBookmark=" + strBookmark);
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallSetValue("cmi.location", strBookmark);
}

function SCORM2004_GetDataChunk(){
	WriteToDebug("In SCORM2004_GetDataChunk");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallGetValue("cmi.suspend_data");
}

function SCORM2004_SetDataChunk(strData){
	WriteToDebug("In SCORM2004_SetDataDChunk");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallSetValue("cmi.suspend_data", strData);
}


function SCORM2004_GetLaunchData(){
	WriteToDebug("In SCORM2004_GetLaunchData");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallGetValue("cmi.launch_data");
}


function SCORM2004_GetComments(){
	
	WriteToDebug("In SCORM2004_GetComments");
	
	SCORM2004_ClearErrorInfo();
	
	var intCommentCount;
	var strComments = "";
	
	intCommentCount = SCORM2004_CallGetValue("cmi.comments_from_learner._count");
	
	for (var i=0; i < intCommentCount; i++){
		
		if (strComments.length > 0){
			strComments += " | ";
		}
		
		strComments += SCORM2004_CallGetValue("cmi.comments_from_learner." + i + ".comment");
	}
	
	return strComments;

}

function SCORM2004_WriteComment(strComment){

	WriteToDebug("In SCORM2004_WriteComment strComment=" + strComment);
	
	var intCurrentIndex;
	var blnResult;
	
	SCORM2004_ClearErrorInfo();	
	
	//remove the "|" since we can use the comments collection
	if (strComment.search(/ \| /) == 0){
		strComment = strComment.substr(3);
	}
	
	//remove encoding of "|"
	strComment.replace(/\|\|/g, "|")
	
	intCurrentIndex = SCORM2004_CallGetValue("cmi.comments_from_learner._count");
	
	blnResult = SCORM2004_CallSetValue("cmi.comments_from_learner." + intCurrentIndex + ".comment", strComment);
	blnResult = blnResult & SCORM2004_CallSetValue("cmi.comments_from_learner." + intCurrentIndex + ".timestamp", ConvertDateToIso8601TimeStamp(new Date()));
	
	return blnResult;
}


function SCORM2004_GetLMSComments(){
	
	WriteToDebug("In SCORM2004_GetLMSComments");
	
	SCORM2004_ClearErrorInfo();
	
	var intCommentCount;
	var strComments = "";
	
	intCommentCount = SCORM2004_CallGetValue("cmi.comments_from_lms._count");
	
	for (var i=0; i < intCommentCount; i++){
		
		if (strComments.length > 0){
			strComments += " \r\n";
		}
		
		strComments += SCORM2004_CallGetValue("cmi.comments_from_lms." + i + ".comment");
	}
	
	return strComments;
}


function SCORM2004_GetAudioPlayPreference(){

	var intTempPreference;
	
	WriteToDebug("In SCORM2004_GetAudioPlayPreference");
	
	SCORM2004_ClearErrorInfo();
	
	intTempPreference = SCORM2004_CallGetValue("cmi.learner_preference.audio_level");
	
	if (intTempPreference == ""){
		intTempPreference = 0;
	}
	
	intTempPreference = parseInt(intTempPreference);
	
	WriteToDebug("intTempPreference=" + intTempPreference);
	
	if (intTempPreference > 0){
		WriteToDebug("Returning On");
		return PREFERENCE_ON;
	}
	else if (intTempPreference <= 0) {
		WriteToDebug("Returning Off");
		return PREFERENCE_OFF;
	}
	else{
		WriteToDebug("Error: Invalid preference");
		SCORM2004_SetErrorInfoManually(SCORM2004_ERROR_INVALID_PREFERENCE, 
								  "Invalid audio preference received from LMS", 
								  "intTempPreference=" + intTempPreference);
		return null;
	}
}



function SCORM2004_GetAudioVolumePreference(){
	
	var intTempPreference;
	
	WriteToDebug("In SCORM2004_GetAudioVollumePreference");
	
	SCORM2004_ClearErrorInfo();
	
	intTempPreference = SCORM2004_CallGetValue("cmi.learner_preference.audio_level");
	
	WriteToDebug("intTempPreference=" + intTempPreference);
	
	if (intTempPreference == "") {
		intTempPreference = 100;
	}
	
	intTempPreference = parseInt(intTempPreference);
	
	if (intTempPreference <= 0){
		WriteToDebug("Setting to 100");
		intTempPreference = 100;
	}
	
	if (! (intTempPreference > 0 && intTempPreference <= 100)){
		WriteToDebug("ERROR: invalid preference");
		SCORM2004_SetErrorInfoManually(SCORM2004_ERROR_INVALID_PREFERENCE, 
								  "Invalid audio preference received from LMS", 
								  "intTempPreference=" + intTempPreference);
		return null;
	}
	
	WriteToDebug("Returning " + intTempPreference);
	return intTempPreference;
	
}

function SCORM2004_SetAudioPreference(PlayPreference, intPercentOfMaxVolume){
	
	WriteToDebug("In SCORM2004_SetAudioPreference PlayPreference=" + PlayPreference + ", intPercentOfMaxVolume=" + intPercentOfMaxVolume);
	
	SCORM2004_ClearErrorInfo();
	
	if (PlayPreference == PREFERENCE_OFF){
		WriteToDebug("Setting percent to 0");
		intPercentOfMaxVolume = 0;
	}
	
	return SCORM2004_CallSetValue("cmi.learner_preference.audio_level", intPercentOfMaxVolume);
}



function SCORM2004_SetLanguagePreference(strLanguage){
	WriteToDebug("In SCORM2004_SetLanguagePreference strLanguage=" + strLanguage);
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallSetValue("cmi.learner_preference.language", strLanguage);

}


function SCORM2004_GetLanguagePreference(){
	WriteToDebug("In SCORM2004_GetLanguagePreference");
	SCORM2004_ClearErrorInfo();
	return SCORM2004_CallGetValue("cmi.learner_preference.language");

}


function SCORM2004_SetSpeedPreference(intPercentOfMax){
	
	//SCORM 2004's scale is greater than 0, our range is 1 to 100, just store our range
	
	WriteToDebug("In SCORM2004_SetSpeedPreference intPercentOfMax=" + intPercentOfMax);

	SCORM2004_ClearErrorInfo();
		
	return SCORM2004_CallSetValue("cmi.learner_preference.delivery_speed", intPercentOfMax);

}


function SCORM2004_GetSpeedPreference(){

	var intSCORMSpeed;
	var intPercentOfMax;
		
	WriteToDebug("In SCORM2004_GetSpeedPreference");

	SCORM2004_ClearErrorInfo();
		
	intSCORMSpeed = SCORM2004_CallGetValue("cmi.learner_preference.delivery_speed");
	
	WriteToDebug("intSCORMSpeed=" + intSCORMSpeed);
	
	if (intSCORMSpeed == ""){
		WriteToDebug("Detected empty string, defaulting to 100");
		intSCORMSpeed = 100;
	}
	
	intSCORMSpeed = parseInt(intSCORMSpeed);
	
	if (intSCORMSpeed < 0){
		WriteToDebug("ERROR - out of range");
		SCORM_SetErrorInfoManually(SCORM_ERROR_INVALID_SPEED, 
								  "Invalid speed preference received from LMS - out of range", 
								  "intSCORMSpeed=" + intSCORMSpeed);	
		return null;
	}

	WriteToDebug("intSCORMSpeed " + intSCORMSpeed);
	
	return intSCORMSpeed;

}




function SCORM2004_SetTextPreference(intPreference){
	
	WriteToDebug("In SCORM2004_SetTextPreference intPreference=" + intPreference);
	
	SCORM2004_ClearErrorInfo();
	
	return SCORM2004_CallSetValue("cmi.learner_preference.audio_captioning", intPreference);

}


function SCORM2004_GetTextPreference(){

	var intTempPreference;
	
	WriteToDebug("In SCORM2004_GetTextPreference");
	
	SCORM2004_ClearErrorInfo();

	intTempPreference = SCORM2004_CallGetValue("cmi.learner_preference.audio_captioning");
	intTempPreference = parseInt(intTempPreference);
	
	WriteToDebug("intTempPreference=" + intTempPreference);
	
	if (intTempPreference > 0){
		WriteToDebug("Returning On");
		return PREFERENCE_ON;
	}
	else if (intTempPreference == 0 || intTempPreference == ""){
		WriteToDebug("Returning Default");
		return PREFERENCE_DEFAULT;
	}
	else if (intTempPreference < 0) {
		WriteToDebug("Returning Off");
		return PREFERENCE_OFF;
	}
	else{
		WriteToDebug("Error: Invalid preference");
		SCORM_SetErrorInfoManually(SCORM_ERROR_INVALID_PREFERENCE, 
								  "Invalid text preference received from LMS", 
								  "intTempPreference=" + intTempPreference);
		return null;
	}
}



//---------------------------------------------------------------------------------
//Time Management Functions
function SCORM2004_GetPreviouslyAccumulatedTime(){
	
	var strIso8601Time;
	var intMilliseconds;
	
	WriteToDebug("In SCORM2004_GetPreviouslyAccumulatedTime");
	

	SCORM2004_ClearErrorInfo();
	
	strIso8601Time = SCORM2004_CallGetValue("cmi.total_time")
	
	WriteToDebug("strIso8601Time=" + strIso8601Time);

	if (! IsValidIso8601TimeSpan(strIso8601Time)){		
		WriteToDebug("ERROR - Invalid Iso8601Time");
		SCORM_SetErrorInfoManually(SCORM_ERROR_INVALID_TIMESPAN, 
									"Invalid timespan received from LMS", 
									"strTime=" + strIso8601Time);	
		return null;
	}
	
	intMilliseconds = ConvertScorm2004TimeToMS(strIso8601Time);
	
	WriteToDebug("Returning " + intMilliseconds);
	
	return intMilliseconds;

}


function SCORM2004_SaveTime(intMilliSeconds){

	var strISO8601Time;
	
	WriteToDebug("In SCORM2004_SaveTime intMilliSeconds=" + intMilliSeconds);
	
	SCORM2004_ClearErrorInfo();
	
	strISO8601Time = ConvertMilliSecondsIntoSCORM2004Time(intMilliSeconds);
	
	WriteToDebug("strISO8601Time=" + strISO8601Time);
	
	return SCORM2004_CallSetValue("cmi.session_time", strISO8601Time);
}

function SCORM2004_GetMaxTimeAllowed(){

	var strIso8601Time;
	var intMilliseconds;
	
	WriteToDebug("In SCORM2004_GetMaxTimeAllowed");


	SCORM2004_ClearErrorInfo();
	
	strIso8601Time = SCORM2004_CallGetValue("cmi.max_time_allowed")
	
	WriteToDebug("strIso8601Time=" + strIso8601Time);
	
	if (strIso8601Time == ""){
		strIso8601Time = "20Y";
	}

	if (! IsValidIso8601TimeSpan(strIso8601Time)){		
		WriteToDebug("ERROR - Invalid Iso8601Time");
		SCORM_SetErrorInfoManually(SCORM_ERROR_INVALID_TIMESPAN, 
									"Invalid timespan received from LMS", 
									"strIso8601Time=" + strIso8601Time);	
		return null;
	}
	
	intMilliseconds = ConvertScorm2004TimeToMS(ConvertScorm2004TimeToMS);
	
	WriteToDebug("intMilliseconds=" + intMilliseconds);
	
	return intMilliseconds;

}



function SCORM2004_DisplayMessageOnTimeout(){

	var strTLA;
	WriteToDebug("In SCORM2004_DisplayMessageOnTimeout");
	
	SCORM2004_ClearErrorInfo();
	
	
	strTLA = SCORM2004_CallGetValue("cmi.time_limit_action");
	
	WriteToDebug("strTLA=" + strTLA);
	
	if (strTLA == SCORM_TLA_EXIT_MESSAGE || strTLA == SCORM_TLA_CONTINUE_MESSAGE){
		WriteToDebug("returning true");
		return true;
	}
	else if(strTLA == SCORM_TLA_EXIT_NO_MESSAGE || strTLA == SCORM_TLA_CONTINUE_NO_MESSAGE || strTLA == ""){
		WriteToDebug("returning false");
		return false;
	}
	else{
		WriteToDebug("Error invalid TLA");
		SCORM_SetErrorInfoManually(SCORM2004_ERROR_INVALID_TIME_LIMIT_ACTION, 
								  "Invalid time limit action received from LMS", 
								  "strTLA=" + strTLA);	
	
		return null;
	}
	
}

function SCORM2004_ExitOnTimeout(){

	var strTLA;
	
	WriteToDebug("In SCORM2004_ExitOnTimeout");
	
	SCORM2004_ClearErrorInfo();
	
	strTLA = SCORM2004_CallGetValue("cmi.time_limit_action");
	
	WriteToDebug("strTLA=" + strTLA);
	
	if (strTLA == SCORM2004_TLA_EXIT_MESSAGE || strTLA == SCORM2004_TLA_EXIT_NO_MESSAGE){
		WriteToDebug("returning true");
		return true;
	}
	else if(strTLA == SCORM2004_TLA_CONTINUE_MESSAGE || strTLA == SCORM2004_TLA_CONTINUE_NO_MESSAGE || strTLA == ""){
		WriteToDebug("returning false");
		return false;
	}
	else{
		WriteToDebug("ERROR invalid TLA");
		SCORM_SetErrorInfoManually(SCORM2004_ERROR_INVALID_TIME_LIMIT_ACTION, 
								  "Invalid time limit action received from LMS", 
								  "strTLA=" + strTLA);	
	
		return null;
	}

}


function SCORM2004_GetPassingScore(){
	var fltScore;
	
	WriteToDebug("In SCORM2004_GetPassingScore");
	
	SCORM2004_ClearErrorInfo();
	
	fltScore = SCORM2004_CallGetValue("cmi.scaled_passing_score")
	
	WriteToDebug("fltScore=" + fltScore);
	
	if (fltScore == ""){
		fltScore = 0;
	}
	
	if ( ! IsValidDecimal(fltScore)){
		WriteToDebug("Error - score is not a valid decimal");
		SCORM_SetErrorInfoManually(SCORM2004_ERROR_INVALID_DECIMAL, 
								  "Invalid mastery score received from LMS", 
								  "fltScore=" + fltScore);		
		return null;
	}
	
	fltScore = parseFloat(fltScore);
	
	//multiply by 100 to normalize from -1 to 1 to 0-100 - (we always set the score so we know it won't be negative)
	fltScore = fltScore * 100;
	
	WriteToDebug("returning fltScore-" + fltScore);
	
	return fltScore;
}


function SCORM2004_SetScore(intScore, intMaxScore, intMinScore){
	
	var blnResult;
	var fltNormalizedScore;

	
	WriteToDebug("In SCORM2004_SetScore intScore=" + intScore + ", intMaxScore=" + intMaxScore + ", intMinScore=" + intMinScore);

	SCORM2004_ClearErrorInfo();
	
	fltNormalizedScore = intScore / 100;
		
	blnResult = SCORM2004_CallSetValue("cmi.score.raw", intScore);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.score.max", intMaxScore);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.score.min", intMinScore);
	
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.score.scaled", fltNormalizedScore);
	
	WriteToDebug("Returning " + blnResult);
	
	return blnResult;
}

function SCORM2004_GetScore(){

		
	WriteToDebug("In SCORM2004_GetScore");
	
	SCORM2004_ClearErrorInfo();
	
	return SCORM2004_CallGetValue("cmi.score.raw");

}

function SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004InteractionType){
	
	var blnResult;
	var intInteractionIndex;
	var strResult;
	
	
	SCORM2004_ClearErrorInfo();
	
	intInteractionIndex = SCORM2004_CallGetValue("cmi.interactions._count");
	
	WriteToDebug("intInteractionIndex=" + intInteractionIndex);
	
	if (intInteractionIndex == ""){
		WriteToDebug("Setting Interaction Index to 0");
		intInteractionIndex = 0;
	}
	
	//need to leave support for blnCorrect=t/f for legacy implementations of RSECA
	if (blnCorrect == true || blnCorrect == INTERACTION_RESULT_CORRECT){
		strResult = SCORM2004_RESULT_CORRECT;
	}
	else if (blnCorrect == "false" || blnCorrect == INTERACTION_RESULT_WRONG){		//compare against the string "false" because ("" == false) evaluates to true
		strResult = SCORM2004_RESULT_WRONG;
	}
	else if (blnCorrect == INTERACTION_RESULT_UNANTICIPATED){
		strResult = SCORM2004_RESULT_UNANTICIPATED;
	}
	else if (blnCorrect == INTERACTION_RESULT_NEUTRAL){
		strResult = SCORM2004_RESULT_NEUTRAL;
	}
	else{
		strResult = "";
	}
	
	WriteToDebug("strResult=" + strResult);
	
	strID = CreateValidIdentifier(strID);
	
	blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".id", strID);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".type", SCORM2004InteractionType);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".learner_response", strResponse);
	
	if (strResult != undefined && strResult != null && strResult != ""){
		blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".result", strResult);
	}
	
	if (strCorrectResponse != undefined && strCorrectResponse != null && strCorrectResponse != ""){
		blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".correct_responses.0.pattern", strCorrectResponse);	
	}
	
	if (strDescription != undefined && strDescription != null && strDescription != ""){
		blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".description", strDescription);
	}
	
	if (intWeighting != undefined && intWeighting != null && intWeighting != ""){
		blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".weighting", intWeighting);
	}

	if (intLatency != undefined && intLatency != null && intLatency != ""){
		blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".latency", ConvertMilliSecondsIntoSCORM2004Time(intLatency));
	}
	
	if (strLearningObjectiveID != undefined && strLearningObjectiveID != null && strLearningObjectiveID != ""){
		blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".objectives.0.id", strLearningObjectiveID);
	}
	
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".timestamp", ConvertDateToIso8601TimeStamp(dtmTime));
	
	WriteToDebug("Returning " + blnResult);
	
	return blnResult;
}

function SCORM2004_RecordTrueFalseInteraction(strID, blnResponse, blnCorrect, blnCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordTrueFalseInteraction strID=" + strID + ", strResponse=" + strResponse + 
					", blnCorrect=" + blnCorrect + ", strCorrectResponse=" + strCorrectResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	

	var strResponse = "";
	var strCorrectResponse = null;
	
	if (blnResponse){
		strResponse = "true";
	}
	else{
		strResponse = "false";
	}
	
	if (blnCorrectResponse == true){
		strCorrectResponse = "true";
	}
	else if(blnCorrectResponse == false){		//test for false b/c it could be null in which case we want to leave it as ""
		strCorrectResponse = "false";
	}	
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004_INTERACTION_TYPE_TRUE_FALSE);
}


function SCORM2004_RecordMultipleChoiceInteraction(strID, aryResponse, blnCorrect, aryCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordMultipleChoiceInteraction strID=" + strID + ", aryResponse=" + aryResponse + 
					", blnCorrect=" + blnCorrect + ", aryCorrectResponse=" + aryCorrectResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	
	
	var strResponse = "";
	var strCorrectResponse = "";
	
	for (var i=0; i < aryResponse.length; i++){
	
		if (strResponse.length > 0) {strResponse += "[,]";}
		strResponse += aryResponse[i].Long;
	}

	for (var i=0; i < aryCorrectResponse.length; i++){
		
		if (strCorrectResponse.length > 0) {strCorrectResponse += "[,]";}
		strCorrectResponse += aryCorrectResponse[i].Long;
	}
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004_INTERACTION_TYPE_CHOICE);
}


function SCORM2004_RecordFillInInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordFillInInteraction strID=" + strID + ", strResponse=" + strResponse + 
					", blnCorrect=" + blnCorrect + ", strCorrectResponse=" + strCorrectResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	
	
	var interactionType;
	
	if (strCorrectResponse == null){
		strCorrectResponse = "";
	}
	
	strCorrectResponse = new String(strCorrectResponse);
	
	if (strCorrectResponse.length > 250 || strResponse.length > 250){
		interactionType = SCORM2004_INTERACTION_LONG_FILL_IN;
	}
	else{
		interactionType = SCORM2004_INTERACTION_FILL_IN;
	}
	
	if (strCorrectResponse.length > 4000){strCorrectResponse = strCorrectResponse.substr(0, 4000);}
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, interactionType);
}

function SCORM2004_RecordMatchingInteraction(strID, aryResponse, blnCorrect, aryCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordMatchingInteraction strID=" + strID + ", aryResponse=" + aryResponse + 
					", blnCorrect=" + blnCorrect + ", aryCorrectResponse=" + aryCorrectResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	
	
	var strResponse = "";
	var strCorrectResponse = "";

	for (var i=0; i < aryResponse.length; i++){
	
		if (strResponse.length > 0) {strResponse += "[,]";}
		strResponse += aryResponse[i].Source.Long + "[.]" + aryResponse[i].Target.Long;
	}

	for (var i=0; i < aryCorrectResponse.length; i++){
		
		if (strCorrectResponse.length > 0) {strCorrectResponse += "[,]";}
		strCorrectResponse += aryCorrectResponse[i].Source.Long + "[.]" + aryCorrectResponse[i].Target.Long;
	}	
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004_INTERACTION_TYPE_MATCHING);
}

function SCORM2004_RecordPerformanceInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordPerformanceInteraction strID=" + strID + ", strResponse=" + strResponse + 
					", blnCorrect=" + blnCorrect + ", strCorrectResponse=" + strCorrectResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	

	strResponse = new String(strResponse);
	if (strResponse.length > 250){strResponse = strResponse.substr(0, 250);}

	if (strCorrectResponse == null){
		strCorrectResponse = "";
	}
		
	strCorrectResponse = new String(strCorrectResponse);
	if (strCorrectResponse.length > 250){strCorrectResponse = strCorrectResponse.substr(0, 250);}
	
	//we're only recording the step answer, not the step name
	strResponse = "[.]" + strResponse;
	strCorrectResponse = "[.]" + strCorrectResponse;
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004_INTERACTION_TYPE_PERFORMANCE);
}

function SCORM2004_RecordSequencingInteraction(strID, aryResponse, blnCorrect, aryCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordSequencingInteraction strID=" + strID + ", aryResponse=" + aryResponse + 
					", blnCorrect=" + blnCorrect + ", aryCorrectResponse=" + aryCorrectResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	

	var strResponse = "";
	var strCorrectResponse = "";
	
	for (var i=0; i < aryResponse.length; i++){
	
		if (strResponse.length > 0) {strResponse += "[,]";}
		strResponse += aryResponse[i].Long;
	}

	for (var i=0; i < aryCorrectResponse.length; i++){
		
		if (strCorrectResponse.length > 0) {strCorrectResponse += "[,]";}
		strCorrectResponse += aryCorrectResponse[i].Long;
	}
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004_INTERACTION_TYPE_SEQUENCING);
}


function SCORM2004_RecordLikertInteraction(strID, response, blnCorrect, correctResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordLikeRatingInteraction strID=" + strID + ", response=" + response + 
					", blnCorrect=" + blnCorrect + ", correctResponse=" + correctResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	
	
	var strResponse = response.Long;
	var strCorrectResponse = "";
	
	if (correctResponse != null){
		strCorrectResponse = correctResponse.Long;
	}
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004_INTERACTION_TYPE_LIKERT);
}

function SCORM2004_RecordNumericInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime){
	
	WriteToDebug("In SCORM2004_RecordNumericInteraction strID=" + strID + ", strResponse=" + strResponse + 
					", blnCorrect=" + blnCorrect + ", strCorrectResponse=" + strCorrectResponse + 
					", strDescription=" + strDescription + ", intWeighting=" + intWeighting + ", intLatency=" + intLatency + 
					", strLearningObjectiveID=" + strLearningObjectiveID + ", dtmTime=" + dtmTime);	
	
	if (strCorrectResponse != undefined && strCorrectResponse != null && strCorrectResponse != ""){
		strCorrectResponse = strCorrectResponse + "[:]" + strCorrectResponse;
	}
	
	return SCORM2004_RecordInteraction(strID, strResponse, blnCorrect, strCorrectResponse, strDescription, intWeighting, intLatency, strLearningObjectiveID, dtmTime, SCORM2004_INTERACTION_TYPE_NUMERIC);
}



function SCORM2004_GetEntryMode(){
	var strEntry;
	
	WriteToDebug("In SCORM2004_GetEntryMode");
	
	SCORM2004_ClearErrorInfo();
	
	strEntry = SCORM2004_CallGetValue("cmi.entry");
	
	WriteToDebug("strEntry=" + strEntry);
	
	if (strEntry == SCORM2004_ENTRY_ABINITIO){
		WriteToDebug("Returning first time");
		return ENTRY_FIRST_TIME;
	}
	else if (strEntry == SCORM2004_ENTRY_RESUME){
		WriteToDebug("Returning resume");
		return ENTRY_RESUME;
	}
	else if (strEntry == SCORM2004_ENTRY_NORMAL){
		WriteToDebug("returning normal");
		return ENTRY_REVIEW;
	}
	else{
		WriteToDebug("ERROR - invalid entry mode");
		SCORM_SetErrorInfoManually(SCORM2004_ERROR_INVALID_ENTRY, 
						"Invalid entry vocab received from LMS", 
						"strEntry=" + strEntry);
		return null;
	}

}

function SCORM2004_GetLessonMode(){

	var strLessonMode;
	
	WriteToDebug("In SCORM2004_GetLessonMode");
	
	SCORM2004_ClearErrorInfo();
	
	strLessonMode = SCORM2004_CallGetValue("cmi.mode");
	
	WriteToDebug("strLessonMode=" + strLessonMode);
	
	if (strLessonMode == SCORM2004_BROWSE){
		WriteToDebug("Returning browse");
		return MODE_BROWSE;
	}
	else if(strLessonMode == SCORM2004_NORMAL){
		WriteToDebug("returning normal");
		return MODE_NORMAL;
	}
	else if(strLessonMode == SCORM2004_REVIEW){
		WriteToDebug("Returning Review");
		return MODE_REVIEW;
	}
	else{
		WriteToDebug("ERROR - invalid lesson mode");
		SCORM_SetErrorInfoManually(SCORM2004_ERROR_INVALID_LESSON_MODE, 
								"Invalid lesson_mode vocab received from LMS", 
								"strLessonMode=" + strLessonMode);
		return null;	
	}
	
}

function SCORM2004_GetTakingForCredit(){
	
	var strCredit;
	
	WriteToDebug("In SCORM2004_GetTakingForCredit");
	
	SCORM2004_ClearErrorInfo();
	
	strCredit = SCORM2004_CallGetValue("cmi.credit");
	
	WriteToDebug("strCredit=" + strCredit);
	
	if (strCredit == "credit"){
		WriteToDebug("Returning true");
		return true;
	}
	else if (strCredit == "no-credit"){
		WriteToDebug("Returning false");
		return false;
	}
	else{
		WriteToDebug("ERROR - invalid credit");
		SCORM_SetErrorInfoManually(SCORM2004_ERROR_INVALID_CREDIT, 
								  "Invalid credit vocab received from LMS", 
								  "strCredit=" + strCredit);
		return null;
	}
}



function SCORM2004_SetObjectiveScore(strObjectiveID, intScore, intMaxScore, intMinScore){
	
	var intObjectiveIndex;
	var blnResult;
	var fltNormalizedScore;
	
	WriteToDebug("In SCORM2004_SetObjectiveScore, strObejctiveID=" + strObjectiveID + ", intScore=" + intScore + ", intMaxScore=" + intMaxScore + ", intMinScore=" + intMinScore);
	
	SCORM2004_ClearErrorInfo();
	
	intObjectiveIndex = SCORM2004_FindObjectiveIndexFromID(strObjectiveID);
	
	WriteToDebug("intObjectiveIndex=" + intObjectiveIndex);
	
	fltNormalizedScore = intScore / 100;
	
	blnResult = SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".id", strObjectiveID);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".score.raw", intScore);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".score.max", intMaxScore);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".score.min", intMinScore);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".score.scaled", fltNormalizedScore);
	
	WriteToDebug("Returning " + blnResult);
	
	return blnResult;
	
}


function SCORM2004_SetObjectiveStatus(strObjectiveID, Lesson_Status){

	var intObjectiveIndex;
	var blnResult;
	var strSCORMSuccessStatus = "";
	var strSCORMCompletionStatus = "";
	
	WriteToDebug("In SCORM2004_SetObjectiveStatus strObjectiveID=" + strObjectiveID + ", Lesson_Status=" + Lesson_Status);
	
	SCORM2004_ClearErrorInfo();
	
	intObjectiveIndex = SCORM2004_FindObjectiveIndexFromID(strObjectiveID);
	
	WriteToDebug("intObjectiveIndex=" + intObjectiveIndex);
	
	if (Lesson_Status == LESSON_STATUS_PASSED){
		strSCORMSuccessStatus = SCORM2004_PASSED;
		strSCORMCompletionStatus = SCORM2004_COMPLETED;
	}
	else if (Lesson_Status == LESSON_STATUS_FAILED){
		strSCORMSuccessStatus = SCORM2004_FAILED;
		strSCORMCompletionStatus = SCORM2004_COMPLETED;
	}
	else if (Lesson_Status == LESSON_STATUS_COMPLETED){
		strSCORMSuccessStatus = SCORM2004_UNKNOWN;
		strSCORMCompletionStatus = SCORM2004_COMPLETED;
	}
	else if (Lesson_Status == LESSON_STATUS_BROWSED){
		strSCORMSuccessStatus = SCORM2004_UNKNOWN;
		strSCORMCompletionStatus = SCORM2004_COMPLETED;
	}
	else if (Lesson_Status == LESSON_STATUS_INCOMPLETE){
		strSCORMSuccessStatus = SCORM2004_UNKNOWN;
		strSCORMCompletionStatus = SCORM2004_INCOMPLETE;
	}
	else if (Lesson_Status == LESSON_STATUS_NOT_ATTEMPTED){
		strSCORMSuccessStatus = SCORM2004_UNKNOWN;
		strSCORMCompletionStatus = SCORM2004_NOT_ATTEMPTED;
	}
	
	WriteToDebug("strSCORMSuccessStatus=" + strSCORMSuccessStatus);
	WriteToDebug("strSCORMCompletionStatus=" + strSCORMCompletionStatus);
	
	blnResult = SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".id", strObjectiveID);
	
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".success_status", strSCORMSuccessStatus);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.objectives." + intObjectiveIndex + ".completion_status", strSCORMCompletionStatus);
	
	WriteToDebug("Returning " + blnResult);
	
	return blnResult;
}



function SCORM2004_GetObjectiveScore(strObjectiveID){

	var intObjectiveIndex;
		
	WriteToDebug("In SCORM2004_GetObjectiveScore, strObejctiveID=" + strObjectiveID);
	
	SCORM2004_ClearErrorInfo();
	
	intObjectiveIndex = SCORM2004_FindObjectiveIndexFromID(strObjectiveID);
	
	WriteToDebug("intObjectiveIndex=" + intObjectiveIndex);

	return SCORM2004_CallGetValue("cmi.objectives." + intObjectiveIndex + ".score.raw");

}


function SCORM2004_GetObjectiveStatus(strObjectiveID){

	var intObjectiveIndex;
	var strSuccessStatus;
	var strCompletionStatus;
	
	WriteToDebug("In SCORM2004_GetObjectiveStatus, strObejctiveID=" + strObjectiveID);
	
	SCORM2004_ClearErrorInfo();
	
	intObjectiveIndex = SCORM2004_FindObjectiveIndexFromID(strObjectiveID);
	
	WriteToDebug("intObjectiveIndex=" + intObjectiveIndex);

	strSuccessStatus = SCORM2004_CallGetValue("cmi.objectives." + intObjectiveIndex + ".success_status");
	strCompletionStatus = SCORM2004_CallGetValue("cmi.objectives." + intObjectiveIndex + ".completion_status");
	
	if (strSuccessStatus == SCORM2004_PASSED){
		WriteToDebug("returning Passed");
		return LESSON_STATUS_PASSED;
	}
	else if (strSuccessStatus == SCORM2004_FAILED){
		WriteToDebug("Returning Failed");
		return LESSON_STATUS_FAILED;
	}
	else if (strCompletionStatus == SCORM2004_COMPLETED){
		WriteToDebug("Returning Completed");
		return LESSON_STATUS_COMPLETED;
	}
	else if (strCompletionStatus == SCORM2004_INCOMPLETE){
		WriteToDebug("Returning Incomplete");
		return LESSON_STATUS_INCOMPLETE;
	}
	else if (strCompletionStatus == SCORM2004_NOT_ATTEMPTED || strCompletionStatus == SCORM2004_UNKNOWN || strStatus == ""){
		WriteToDebug("Returning Not Attempted");
		return LESSON_STATUS_NOT_ATTEMPTED;
	}
	else{
		WriteToDebug("ERROR - status not found");
		SCORM_SetErrorInfoManually(SCORM2004_ERROR_INVALID_STATUS, 
								"Invalid objective status received from LMS or initial status not yet recorded for objective", 
								"strStatus=" + strStatus);
		return null;

	}	

}


function SCORM2004_FindObjectiveIndexFromID(strObjectiveID){

	var intCount;
	var i;
	var strTempID;
	
	WriteToDebug("In SCORM2004_FindObjectiveIndexFromID");
	
	intCount = SCORM2004_CallGetValue("cmi.objectives._count");
	
	if (intCount == ""){
		WriteToDebug("Setting intCount=0");
		return 0;
	}
	
	intCount = parseInt(intCount);
	
	WriteToDebug("intCount=" + intCount);
	
	for (i=0; i<intCount; i++){
	
		WriteToDebug("Checking index " + i);
		
		strTempID = SCORM2004_CallGetValue("cmi.objectives." + i + ".id");
		
		WriteToDebug("ID=" + strTempID);
		
		if (strTempID == strObjectiveID){
			WriteToDebug("Found Matching index");
			return i;
		}
	}
	
	WriteToDebug("Did not find match, returning count");
	
	return intCount;
}


//---------------------------------------------------------------------------------
//Status Management Functions

function SCORM2004_SetFailed(){
	
	WriteToDebug("In SCORM2004_SetFailed");
	
	var blnResult;
	
	SCORM2004_ClearErrorInfo();
	
	blnResult = SCORM2004_CallSetValue("cmi.success_status", SCORM2004_FAILED);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.completion_status", SCORM2004_COMPLETED);
	
	return blnResult;
}

function SCORM2004_SetPassed(){

	WriteToDebug("In SCORM2004_SetPassed");
	
	var blnResult;
	
	SCORM2004_ClearErrorInfo();
	
	blnResult = SCORM2004_CallSetValue("cmi.success_status", SCORM2004_PASSED);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.completion_status", SCORM2004_COMPLETED);
	
	return blnResult;
}

function  SCORM2004_SetCompleted(){

	WriteToDebug("In SCORM2004_SetCompleted");
	
	var blnResult;
	
	SCORM2004_ClearErrorInfo();
	
	blnResult = SCORM2004_CallSetValue("cmi.completion_status", SCORM2004_COMPLETED);
	
	return blnResult;
}

function SCORM2004_ResetStatus(){
	
	WriteToDebug("In SCORM2004_ResetStatus");
	
	var blnResult;
	
	SCORM2004_ClearErrorInfo();
	
	blnResult = SCORM2004_CallSetValue("cmi.success_status", SCORM2004_UNKNOWN);
	blnResult = blnResult && SCORM2004_CallSetValue("cmi.completion_status", SCORM2004_INCOMPLETE);
	
	return blnResult;
}

function SCORM2004_GetStatus(){
	
	var strSuccessStatus;
	var strCompletionStatus;
	
	WriteToDebug("In SCORM2004_GetStatus");
	
	SCORM2004_ClearErrorInfo();
	
	strSuccessStatus = SCORM2004_CallGetValue("cmi.success_status");
	strCompletionStatus = SCORM2004_CallGetValue("cmi.completion_status");
	
	WriteToDebug("strSuccessStatus=" + strSuccessStatus);
	WriteToDebug("strCompletionStatus=" + strCompletionStatus);
	
	if (strSuccessStatus == SCORM2004_PASSED){
		WriteToDebug("returning Passed");
		return LESSON_STATUS_PASSED;
	}
	else if (strSuccessStatus == SCORM2004_FAILED){
		WriteToDebug("Returning Failed");
		return LESSON_STATUS_FAILED;
	}
	else if (strCompletionStatus == SCORM2004_COMPLETED){
		WriteToDebug("Returning Completed");
		return LESSON_STATUS_COMPLETED;
	}
	else if (strCompletionStatus == SCORM2004_INCOMPLETE){
		WriteToDebug("Returning Incomplete");
		return LESSON_STATUS_INCOMPLETE;
	}
	else if (strCompletionStatus == SCORM2004_NOT_ATTEMPTED || strCompletionStatus == SCORM2004_UNKNOWN){
		WriteToDebug("Returning Not Attempted");
		return LESSON_STATUS_NOT_ATTEMPTED;
	}
	else{
		WriteToDebug("ERROR - status not found");
		SCORM_SetErrorInfoManually(SCORM_ERROR_INVALID_STATUS, 
								"Invalid lesson status received from LMS", 
								"strStatus=" + strStatus);
		return null;

	}
	
					
}



function SCORM2004_IsContentInBrowseMode(){
	
	var strLessonMode
	
	WriteToDebug("In SCORM2004_IsContentInBrowseMode");
	
	strLessonMode = SCORM2004_CallGetValue("cmi.mode");
	
	WriteToDebug("SCORM2004_IsContentInBrowseMode,  strLessonMode=" + strLessonMode);
	
	if (strLessonMode == SCORM2004_BROWSE){
		WriteToDebug("Returning true");
		return true;
	}
	else{
		WriteToDebug("Returning false");
		return false;
	}
}


function SCORM2004_TranslateExitTypeToSCORM(strExitType){
	
	WriteToDebug("In SCORM2004_TranslatgeExitTypeToSCORM strExitType-" + strExitType);
	
	if (strExitType == EXIT_TYPE_SUSPEND){
		WriteToDebug("Returning suspend");
		return SCORM2004_SUSPEND;
	}
	else if (strExitType == EXIT_TYPE_UNLOAD){
		WriteToDebug("Returning Exit");
		return SCORM2004_NORMAL_EXIT;
	}
	else if (strExitType == EXIT_TYPE_FINISH){
		WriteToDebug("Returning Logout");
		return SCORM2004_NORMAL_EXIT;
	}
	else if (strExitType == EXIT_TYPE_TIMEOUT){
		WriteToDebug("Returning Timout");
		return SCORM2004_TIMEOUT;
	}
}


function SCORM2004_GetCompletionStatus(){
	
	WriteToDebug("In SCORM2004_GetCompletionStatus");
	
	return SCORM2004_COMPLETED;
	
}





//---------------------------------------------------------------------------------
//Functions to Call the SCORM API

//note: in all functions that interact with API, we concact any returned strings with "" to convert
//the value to a string type, do this b/c many SCORM API's will return a Java String instead of a Javascript
//string


function SCORM2004_CallInitialize(){

	var strResult;
	
	WriteToDebug("In SCORM2004_CallInitialize");
	
	SCORM2004_objAPI = SCORM2004_GrabAPI();
	
	WriteToDebug("Calling Initialize");
	
	strResult = SCORM2004_objAPI.Initialize("");
	strResult = strResult + "";
	
	WriteToDebug("strResult=" + strResult);
	
	if (strResult == SCORM2004_FALSE){
		
		WriteToDebug("Detected failed call to initialize");
		
		SCORM2004_SetErrorInfo();
		
		WriteToDebug ("Error calling Initialize:");
		WriteToDebug ("              Error Number=" + intSCORM2004Error);
		WriteToDebug ("              Error String=" + strSCORM2004ErrorString);
		WriteToDebug ("              Diagnostic=" + strSCORM2004ErrorDiagnostic);
		
		return false;

	}
	
	WriteToDebug("Returning true");
	
	return true;
}

function SCORM2004_CallSetValue(strElement, strValue){
	
	var strResult;
	
	WriteToDebug("SCORM2004_CallSetValue strElement=" + strElement + ", strValue=" + strValue);
	
	SCORM2004_objAPI = SCORM2004_GrabAPI();		
	
	WriteToDebug("Calling SetValue");
	
	strElement = strElement + "";
	strValue = strValue + "";
	
	strResult = SCORM2004_objAPI.SetValue(strElement, strValue)
	strResult = strResult + "";
	
	WriteToDebug("strResult=" + strResult);
	
	if (strResult == SCORM2004_FALSE){
		
		WriteToDebug("Detected Failed call to SetValue");
		
		SCORM2004_SetErrorInfo();
		
		WriteToDebug ("Error calling SetValue:");
		WriteToDebug ("              strElement=" + strElement);
		WriteToDebug ("              strValue=" + strValue);
		WriteToDebug ("              Error Number=" + intSCORM2004Error);
		WriteToDebug ("              Error String=" + strSCORM2004ErrorString);
		WriteToDebug ("              Diagnostic=" + strSCORM2004ErrorDiagnostic);
		
		return false;
	}
	
	WriteToDebug("Returning true");
	
	return true;
}

function SCORM2004_CallGetValue(strElement){

	var strResult
	
	WriteToDebug("In SCORM2004_CallGetValue strElement=" + strElement);
	
	SCORM2004_objAPI = SCORM2004_GrabAPI();	
	
	WriteToDebug("Call GetValue");

	strElement = strElement + "";
		
	strResult = SCORM2004_objAPI.GetValue(strElement) + ""
	
	WriteToDebug("strResult=" + strResult);
	
	intSCORM2004Error = SCORM2004_objAPI.GetLastError()
	intSCORM2004Error = intSCORM2004Error + "";
	
	WriteToDebug("intSCORM2004Error=" + intSCORM2004Error);
	
	if (intSCORM2004Error != SCORM2004_NO_ERROR){	
		
		WriteToDebug("Detected failed called to GetValue");
		
		SCORM2004_SetErrorInfo();
		
		WriteToDebug ("Error calling LMSGetValue:");
		WriteToDebug ("              strElement=" + strElement);
		WriteToDebug ("              Error Number=" + intSCORM2004Error);
		WriteToDebug ("              Error String=" + strSCORM2004ErrorString);
		WriteToDebug ("              Diagnostic=" + strSCORM2004ErrorDiagnostic);
	}
	
	WriteToDebug("Returning " + strResult);
	
	return strResult;
	
}


function SCORM2004_CallCommit(){
	
	var strResult;
	
	WriteToDebug("In SCORM2004_CallCommit");
	
	SCORM2004_objAPI = SCORM2004_GrabAPI();
		
	WriteToDebug("Calling Commit");	
	
	strResult = SCORM2004_objAPI.Commit("");
	
	strResult = strResult + "";
	
	WriteToDebug("strResult=" + strResult);
	
	if (strResult == SCORM2004_FALSE){
		
		WriteToDebug("Detected failed call to Commit");
		
		SCORM2004_SetErrorInfo();
		
		WriteToDebug ("Error calling Commit:");
		WriteToDebug ("              Error Number=" + intSCORM2004Error);
		WriteToDebug ("              Error String=" + strSCORM2004ErrorString);
		WriteToDebug ("              Diagnostic=" + strSCORM2004ErrorDiagnostic);
		
		return false;
	}
	
	WriteToDebug("Returning true");
	
	return true;
}


function SCORM2004_CallTerminate(){
	
	var strResult;
	
	WriteToDebug("In SCORM2004_CallTerminate");
	
	SCORM2004_objAPI = SCORM2004_GrabAPI();
	
	WriteToDebug("Calling Terminate");
	
	strResult = SCORM2004_objAPI.Terminate("");
	
	strResult = strResult + "";
	
	WriteToDebug("strResult=" + strResult);
	
	if (strResult == SCORM2004_FALSE){
		
		WriteToDebug("Detected failed call to Terminate");
		
		SCORM2004_SetErrorInfo();
		
		WriteToDebug ("Error calling Terminate:");
		WriteToDebug ("              Error Number=" + intSCORM2004Error);
		WriteToDebug ("              Error String=" + strSCORM2004ErrorString);
		WriteToDebug ("              Diagnostic=" + strSCORM2004ErrorDiagnostic);
		
		return false;
	}
	
	WriteToDebug("Returning True");
	
	return true;
}


//---------------------------------------------------------------------------------
//Error Handling Functions
function SCORM2004_ClearErrorInfo(){
	
	WriteToDebug("In SCORM2004_ClearErrorInfo");
	
	intSCORM2004Error = SCORM_NO_ERROR;
	strSCORM2004ErrorString = "";
	strSCORM2004ErrorDiagnostic = "";
}

function SCORM2004_SetErrorInfo(){
	
	WriteToDebug("In SCORM2004_SetErrorInfo");
	
	intSCORM2004Error = SCORM2004_objAPI.GetLastError();
	strSCORM2004ErrorString = SCORM2004_objAPI.GetErrorString(intSCORM2004Error);
	strSCORM2004ErrorDiagnostic = SCORM2004_objAPI.GetDiagnostic("");
	
	intSCORM2004Error = intSCORM2004Error + "";
	strSCORM2004ErrorString = strSCORM2004ErrorString + "";
	strSCORM2004ErrorDiagnostic = strSCORM2004ErrorDiagnostic + "";
	
	WriteToDebug("intSCORM2004Error=" + intSCORM2004Error);
	WriteToDebug("strSCORM2004ErrorString=" + strSCORM2004ErrorString);
	WriteToDebug("strSCORM2004ErrorDiagnostic=" + strSCORM2004ErrorDiagnostic);
}

function SCORM2004_SetErrorInfoManually(intNum, strString, strDiagnostic){
		
		WriteToDebug("In SCORM2004_SetErrorInfoManually");
		WriteToDebug("ERROR-Num=" + intNum);	
		WriteToDebug("      String=" + strString);	
		WriteToDebug("      Diag=" + strDiagnostic);
		
		intSCORM2004Error = intNum;
		strSCORM2004ErrorString = strString;
		strSCORM2004ErrorDiagnostic = strDiagnostic;	

}

function SCORM2004_GetLastError(){
	
	WriteToDebug("In SCORM2004_GetLastError");
	
	if (intSCORM2004Error == SCORM2004_NO_ERROR){
		WriteToDebug("Returning No Error");
		return NO_ERROR;
	}
	else {
		WriteToDebug("Returning " + intSCORMError);
		return intSCORM2004Error;
	}
}

function SCORM2004_GetLastErrorDesc(){
	WriteToDebug("In SCORM2004_GetLastErrorDesc, " + strSCORM2004ErrorString + "\n" + strSCORM2004ErrorDiagnostic);
	return strSCORM2004ErrorString + "\n" + strSCORM2004ErrorDiagnostic;
}



//---------------------------------------------------------------------------------
//API Locating Functions

function SCORM2004_GrabAPI(){
	
	WriteToDebug("In SCORM2004_GrabAPI");
	
	if (typeof(SCORM2004_objAPI) == "undefined" || SCORM2004_objAPI == null){
		WriteToDebug("Searching with Rustici Software algorithm");
		SCORM2004_objAPI = SCORM2004_GetAPI();
	}
	
	WriteToDebug("Grab API, returning, found API = " + (SCORM2004_objAPI != null));
	
	return SCORM2004_objAPI;

}




/*******************************************************************
	* SCORM 2004 API Search Algorithm
	* Description - Improvement of the algorithm developed by ADL to 
		find the SCORM 2004 API Adapter. The improvements eliminate 
		errors, improve code clarity and eliminate the dependence
		on global variables. The errors removed include:
			- The "win" variable was never declared in a scope 
			  accessible to the GetAPI function
			- A call to API.version which is not part of the SCORM
			  2004 specification
			- The previous algorithm was not able to find the API
			  if it was located in the window's parent's opener
	* Original Author - ADL & Concurrent Technologies Corporation
	* Author -  Mike Rustici (April 1, 2004)
				Rustici Software, LLC
				http://www.scorm.com
				mike@scorm.com
*******************************************************************/




/*
ScanParentsForApi
-Searches all the parents of a given window until
 it finds an object named "API_1484_11". If an
 object of that name is found, a reference to it
 is returned. Otherwise, this function returns null.
*/
function SCORM2004_ScanParentsForApi(win) 
{ 

	/*
	Establish an outrageously high maximum number of
	parent windows that we are will to search as a
	safe guard against an infinite loop. This is 
	probably not strictly necessary, but different 
	browsers can do funny things with undefined objects.
	*/
	var MAX_PARENTS_TO_SEARCH = 500; 
	var nParentsSearched = 0;
	
	/*
	Search each parent window until we either:
		 -find the API, 
		 -encounter a window with no parent (parent is null 
				or the same as the current window)
		 -or, have reached our maximum nesting threshold
	*/
	while ( (win.API_1484_11 == null) && 
			(win.parent != null) && (win.parent != win) && 
			(nParentsSearched <= MAX_PARENTS_TO_SEARCH) 
		  )
	{ 
				
		nParentsSearched++; 
		win = win.parent;
	} 
	
	/*
	If the API doesn't exist in the window we stopped looping on, 
	then this will return null.
	*/
	return win.API_1484_11; 
} 


/*
GetAPI
-Searches all parent and opener windows relative to the
 current window for the SCORM 2004 API Adapter.
 Returns a reference to the API Adapter if found or null
 otherwise.
*/
function SCORM2004_GetAPI() 
{ 
	
	var API = null; 
	
	//Search all the parents of the current window if there are any
	if ((window.parent != null) && (window.parent != window)) 
	{ 
		API = SCORM2004_ScanParentsForApi(window.parent); 
	} 
	
	/*
	If we didn't find the API in this window's chain of parents, 
	then search all the parents of the opener window if there is one
	*/
	if ((API == null) && (window.top.opener != null))
	{ 
		API = SCORM2004_ScanParentsForApi(window.top.opener); 
	} 
	
	return API;
}




