/*******************************************************************************
**
** Filename: SCOFunctions.js
**
** File Description: This file contains several JavaScript functions that are
**                   used by the Sample SCOs contained in the Sample Course.
**                   These functions encapsulate actions that are taken when the
**                   user navigates between SCOs, or exits the Lesson.
**
** Author: ADL Technical Team
**
** Contract Number:
** Company Name: CTC
**
** Design Issues:
**
** Implementation Issues:
** Known Problems:
** Side Effects:
**
** References: ADL SCORM
**
** Modified by: M. Lawn - MountainTop Technologies Inc.
** Modification Date: 12/11/2003
** Modification Date: 04/13/2004
**   Change Description: Stripped # from the end of the location.href in unload
**                       function, to fix bookmarking.
**
** Modified by: J. Eckenrode - MountainTop Technologies Inc.
** Modification Date: 02/2008
**   Change Description: Added lessonStatus, lmsConnected, SCORMversion, and
**                       verbose variables and related functionality.
**
/*******************************************************************************
**
** Concurrent Technologies Corporation (CTC) grants you ("Licensee") a non-
** exclusive, royalty free, license to use, modify and redistribute this
** software in source and binary code form, provided that i) this copyright
** notice and license appear on all copies of the software; and ii) Licensee
** does not utilize the software in a manner which is disparaging to CTC.
**
** This software is provided "AS IS," without a warranty of any kind.  ALL
** EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
** IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-
** INFRINGEMENT, ARE HEREBY EXCLUDED.  CTC AND ITS LICENSORS SHALL NOT BE LIABLE
** FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
** DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL CTC  OR ITS
** LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
** INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
** CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
** OR INABILITY TO USE SOFTWARE, EVEN IF CTC  HAS BEEN ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGES.
**
*******************************************************************************/


// string : The date the course was started
var startDate;
// boolean : Whether or not the course has been exited
var exitPageStatus;
// string : Set in loadPage() function to be used for bookmarking
var courseFirstPage;
// string : Status of current SCO
var lessonStatus;
// Indicates whether course is connected to an LMS
var lmsConnected;
// Indicates SCORM version
var SCORMversion;
// Used to turn api detection error messages on and off
var verbose = false;


//Check for LMS connection and SCORM version.
getAPIversion();


/*******************************************************************************
** Purpose: Sets the current time.
**
** Inputs: nothing
** Returns: nothing
**
** Created by ADL Technical Team
*******************************************************************************/
function startTimer()
{
   startDate = new Date().getTime();
}


/*******************************************************************************
** Purpose: This function will convert seconds into hours, minutes, and seconds
**          in CMITimespan type format - HHHH:MM:SS.SS (Hours has a max of 4
**          digits & Min of 2 digits
**
** Inputs: ts - The time to be converted
** Returns: nothing
**
** Created by ADL Technical Team
** Edited by J. Eckenrode, 2/2008 -- Added SCORM version test and
**                                  2004 time format -- T[hH][mM][s[.s]S]
*******************************************************************************/
function convertTotalSeconds(ts)
{
   var sec = (ts % 60);

   ts -= sec;
   var tmp = (ts % 3600);  //# of seconds in the total # of minutes
   ts -= tmp;              //# of seconds in the total # of hours

   // convert seconds to conform to CMITimespan type (e.g. SS.00)
   sec = Math.round(sec*100)/100;

   var strSec = new String(sec);
   var strWholeSec = strSec;
   var strFractionSec = "";

   if (strSec.indexOf(".") != -1)
   {
      strWholeSec =  strSec.substring(0, strSec.indexOf("."));
      strFractionSec = strSec.substring(strSec.indexOf(".")+1, strSec.length);
   }

   if (strWholeSec.length < 2)
   {
      strWholeSec = "0" + strWholeSec;
   }
   strSec = strWholeSec;

   if (strFractionSec.length)
   {
      strSec = strSec+ "." + strFractionSec;
   }


   if ((ts % 3600) != 0 )
      var hour = 0;
   else var hour = (ts / 3600);
   if ( (tmp % 60) != 0 )
      var min = 0;
   else var min = (tmp / 60);

   if ((new String(hour)).length < 2)
      hour = "0"+hour;
   if ((new String(min)).length < 2)
      min = "0"+min;


   var returnTime;

   switch(SCORMversion) {
      case "1.2":
         returnTime = hour + ":" + min + ":" + strSec;
         break;
      case "2004":
         returnTime = "T" + hour + "H" + min + "M" + strSec + "S";
         break;
      default:
         returnTime = null;
         break;
   }


   return returnTime;

}


/*******************************************************************************
** Purpose: Determines how long the student has been in the course.
**
** Inputs: nothing
** Returns: nothing
**
** Created by ADL Technical Team
** Edited by J. Eckenrode, 2/2008 -- Added SCORM version test.
*******************************************************************************/
function computeTime()
{
   if ( startDate != 0 )
   {
      var currentDate = new Date().getTime();
      var elapsedSeconds = ( (currentDate - startDate) / 1000 );
      var formattedTime = convertTotalSeconds( elapsedSeconds );
   }
   else
   {


      switch(SCORMversion) {
         case "1.2":
            formattedTime = "00:00:00.0";
            break;
         case "2004":
            formattedTime = "T0H0M0S";
            break;
         default:
            formattedTime = null;
            break;
      }


   }


   switch(SCORMversion) {
      case "1.2":
         doLMSSetValue("cmi.core.session_time", formattedTime);
         break;
      case "2004":
         doLMSSetValue("cmi.session_time", "P" + formattedTime);
         break;
      default:
         break;
   }


}


/*******************************************************************************
** Purpose: Called when course is opened.
**
** Inputs: nothing
** Returns: nothing
**
** Created by ADL Technical Team
** Edited by M. Lawn - Added the Bookmark feature
** Edited by J. Eckenrode, 2/2008 - Added LMS connection test, SCORM version
**                                 test, and lessonStatus.
*******************************************************************************/
function loadPage(pge) {
	
	if (!lmsConnected) return pge;

	var chkStatus;
	var bkmPge;

	var result = doLMSInitialize();


	//Get lesson status.
	switch(SCORMversion) {
		case "1.2":
			chkStatus = doLMSGetValue("cmi.core.lesson_status");
			break;
		case "2004":
			chkStatus = doLMSGetValue("cmi.completion_status");
			break;
		default:
			break;
	}


	if (chkStatus == "not attempted" || chkStatus == "unknown") {
		//Update status.
		lessonStatus = "incomplete"
	
		switch(SCORMversion) {
			case "1.2":
				result = doLMSSetValue("cmi.core.lesson_status", lessonStatus);
				break;
			case "2004":
				result = doLMSSetValue("cmi.completion_status", lessonStatus);
				break;
			default:
				break;
		}
	}
	else lessonStatus = chkStatus;


	if (lessonStatus == "completed" || lessonStatus == "passed") {
		bkmPge = pge;
	}
	else {
		//Get bookmark.
		switch(SCORMversion) {
			case "1.2":
				bkmPge = doLMSGetValue('cmi.core.lesson_location');
				break;
			case "2004":
				bkmPge = doLMSGetValue('cmi.location');
				break;
			default:
				break;
		}
		if (!bkmPge || bkmPge == "") bkmPge = pge;
	}


	courseFirstPage = pge;
	exitPageStatus = false;
	startTimer();


	return bkmPge;

}


/*******************************************************************************
** Purpose: NOT USED
**
** Inputs: nothing
** Returns: nothing
**
** Created by ADL Technical Team
** Edited by J. Eckenrode, 2/2008 - Added SCORM version test.
*******************************************************************************/
function doBack()
{

   switch(SCORMversion) {
      case "1.2":
         doLMSSetValue("cmi.core.exit", "suspend");
         break;
      case "2004":
         doLMSSetValue("cmi.exit", "suspend");
         break;
      default:
         break;
   }


   computeTime();
   exitPageStatus = true;

   var result;
   result = doLMSCommit();
   // NOTE: LMSFinish will unload the current SCO.  All processing
   //       relative to the current page must be performed prior
   //       to calling LMSFinish.
   result = doLMSFinish();


}


/*******************************************************************************
** Purpose: NOT USED
**
** Inputs: nothing
** Returns: nothing
**
** Created by ADL Technical Team
** Edited by J. Eckenrode, 2/2008 - Added SCORM version test.
*******************************************************************************/
function doContinue( status )
{
   // Reinitialize Exit to blank
   switch(SCORMversion) {
      case "1.2":
         doLMSSetValue("cmi.core.exit", "");
         break;
      case "2004":
         doLMSSetValue("cmi.exit", "");
         break;
      default:
         break;
   }


   switch(SCORMversion) {
      case "1.2":
         var mode = doLMSGetValue("cmi.core.lesson_mode");
         break;
      case "2004":
         var mode = doLMSGetValue("cmi.mode");
         break;
      default:
         break;
   }


   if ( mode != "review"  &&  mode != "browse" )
   {


      switch(SCORMversion) {
         case "1.2":
            doLMSSetValue("cmi.core.lesson_status", status);
            break;
         case "2004":
            doLMSSetValue("cmi.completion_status", status);
            break;
         default:
            break;
      }


   }

   computeTime();
   exitPageStatus = true;

   var result;
   result = doLMSCommit();
   // NOTE: LMSFinish will unload the current SCO.  All processing
   //       relative to the current page must be performed prior
   //       to calling LMSFinish.
   result = doLMSFinish();

}


/*******************************************************************************
** Purpose: Called to set the status of the lesson when the user exits.
**
** Inputs: status - cmi.core.lesson_status setting
** Returns: nothing
**
** Created by ADL Technical Team
** Edited by J. Eckenrode, 2/2008 - Added SCORM version test.
*******************************************************************************/
function doQuit(status) {

   status = status.toLowerCase();

   computeTime();
   exitPageStatus = true;

   var result = doLMSCommit();


   switch(SCORMversion) {
      case "1.2":
         doLMSSetValue("cmi.core.lesson_status", status);
         break;
      case "2004":
         doLMSSetValue("cmi.completion_status", status);
         break;
      default:
         break;
   }


   if (status == "completed" || status == "passed") {


      switch(SCORMversion) {
         case "1.2":
            doLMSSetValue("cmi.core.exit", "");
            break;
         case "2004":
            doLMSSetValue("cmi.exit", "normal");
            break;
         default:
            break;
      }


   } 

   else {


      switch(SCORMversion) {
         case "1.2":
            doLMSSetValue("cmi.core.exit", "suspend");
            break;
         case "2004":
            doLMSSetValue("cmi.exit", "suspend");
            break;
         default:
            break;
      }


   }


   // NOTE: LMSFinish will unload the current SCO.  All processing
   //       relative to the current page must be performed prior
   //       to calling LMSFinish.
   result = doLMSFinish();

}


/*******************************************************************************
** Purpose: The purpose of this function is to handle cases where the current
**          SCO may be unloaded via some user action other than using the
**          navigation controls embedded in the content.   This function will be
**          called every time an SCO is unloaded.  If the user has caused the
**          page to be unloaded through the preferred SCO control mechanisms,
**          the value of the "exitPageStatus" var will be true so we'll just
**          allow the page to be unloaded.   If the value of "exitPageStatus" is
**          false, we know the user caused the page to be unloaded through use
**          of some other mechanism... most likely the back button on the browser
**          We'll handle this situation the same way we would handle a "quit" -
**          as in the user pressing the SCO's quit button.
**
** Inputs: status - cmi.core.lesson_status setting
** Returns: nothing
**
** Created by ADL Technical Team
** Edited by M. Lawn - Added the Bookmark feature
** Edited by J. Eckenrode, 2/2008 - Added LMS connection test and
**                                 SCORM version test.
*******************************************************************************/
function unloadPage(status) {

	if (!lmsConnected) return;
	if (exitPageStatus) return;

	status = status.toLowerCase();


	//Set Bookmark.
	if (status == "completed" || status == "passed") bkmPge = courseFirstPage.toString()
	else {
		bkmPge = courseFrame.document.getElementById("iContent").src;
		if (bkmPge.charAt(bkmPge.length - 1) == "#") bkmPge = bkmPge.substring(0, bkmPge.length - 1);
		bkmPge = bkmPge.substring(bkmPge.lastIndexOf('/') + 1, bkmPge.length);
		if (bkmPge.substring(bkmPge.lastIndexOf('/') + 1, bkmPge.length - 7) != coursePagePrefix + courseNumber + "_" + courseSection) {
			bkmPge = courseFirstPage.toString();
		}
	}
	setBookmark(bkmPge);


	switch(SCORMversion) {
		case "1.2":
			var chk_status = doLMSGetValue("cmi.core.lesson_status");
			if (chk_status == "completed" || chk_status == "passed") status = chk_status;
			break;
		case "2004":
			var chk_status = doLMSGetValue("cmi.completion_status");
			if (chk_status == "completed") status = chk_status;
			break;
		default:
			break;
	}


	doQuit(status);

// NOTE: Don't return anything that resembles a javascript
//       string from this function or IE will take the
//       liberty of displaying a confirm message box.

}


/*******************************************************************************
** Purpose: Called to set a bookmark when the course is closed or exited.
**
** Inputs: bkmPge - The file name of the page to bookmark.
** Returns: nothing
**
** Created by M. Lawn
** Edited by J. Eckenrode, 2/2008 - Added SCORM version test.
*******************************************************************************/
function setBookmark(bkmPge)
{

   switch(SCORMversion) {
      case "1.2":
         doLMSSetValue('cmi.core.lesson_location', bkmPge);
         break;
      case "2004":
         doLMSSetValue('cmi.location', bkmPge);
         break;
      default:
         break;
   }


   var result = doLMSCommit();

}


/*******************************************************************************
** Purpose: Called when course is closed or exited, it will set the status to
**          either incomplete or complete depending on the page it is on.
**
** Inputs: nothing
** Returns: nothing
**
** Created by M. Lawn
*******************************************************************************/
function determineExitStatus()
{
  if (!exitPageStatus)
  {
    if(coursePage == arrPages[arrPages.length-1]) {
      unloadPage('completed');
    }
    else
    {
      unloadPage('incomplete');
    }
  }
}


/*******************************************************************************
** Purpose: Called to set the completion status of a SCO.
** Inputs: status - The status of the SCO.
**
** Returns: nothing
**
** Created by J. Eckenrode, 4/2008
*******************************************************************************/
function completeSCO(status) {

	if (!lmsConnected) return;
	if (exitPageStatus) return;

	status = status.toLowerCase();

	switch(SCORMversion) {
		case "1.2":
			doLMSSetValue("cmi.core.lesson_status", status);
			break;
		case "2004":
			doLMSSetValue("cmi.completion_status", status);
			break;
		default:
			break;
	}

}


/*******************************************************************************
** Purpose: Called to set the score of the assessment.
** Inputs: status - The status of the course (passed or failed)
**         score - The current assessment score.
**
** Returns: nothing
**
** Created by M. Lawn
** Edited by J. Eckenrode, 2/2008 - Added LMS connection test
**                                 and SCORM version test.
*******************************************************************************/
function completeExam(status, score) {

	if (!lmsConnected) return;
	if (exitPageStatus) return;

	var chk_status;
	status = status.toLowerCase();


	switch(SCORMversion) {
		case "1.2":
			chk_status = doLMSGetValue("cmi.core.lesson_status");
			break;
		case "2004":
			chk_status = doLMSGetValue("cmi.success_status");
			break;
		default:
			break;
	}


	if (chk_status == "passed") status = chk_status
	else {

		switch(SCORMversion) {
			case "1.2":
				doLMSSetValue("cmi.core.score.raw", score);
				break;
			case "2004":
				doLMSSetValue("cmi.score.raw", score);
				break;
			default:
				break;
		}

	}


	switch(SCORMversion) {
		case "1.2":
			doLMSSetValue("cmi.core.lesson_status", status);
			lessonStatus = status;
			break;
		case "2004":
			if (status == "passed") lessonStatus = "completed"
			else if (status == "failed") lessonStatus = "incomplete"
			doLMSSetValue("cmi.success_status", status);
			doLMSSetValue("cmi.completion_status", lessonStatus);
			break;
		default:
			break;
	}


}


/*******************************************************************************
** Purpose: Called to set the interactions of the assessment.
** Inputs: name - The name of the question, spaces will be removed
**         type - The type of question: true-false, choice, fill-in, matching,
**                peformance, sequencing, likert, numeric
**         response - The answwer the student chose
**         pattern - The correct answer to the question.
**         result - The outcome of the answer: correct, wrong, unanticipated,
**                  neutral
**
** Returns: nothing
**
** Created by M. Lawn
** Edited by J. Eckenrode, 2/2008 - Added LMS connection test and SCORM version
**                                 test. Removed parsing of interaction name.
*******************************************************************************/
function examInteractions(name,type,response,pattern,result) {

	if (!lmsConnected) return;

	var chk_status;


	switch(SCORMversion) {
		case "1.2":
			chk_status = doLMSGetValue("cmi.core.lesson_status");
			break;
		case "2004":
			chk_status = doLMSGetValue("cmi.completion_status");
			break;
		default:
			break;
	}


	if (chk_status != "passed" && chk_status != "completed")
	{
		var n = doLMSGetValue("cmi.interactions._count");

		if ( (SCORMversion == "2004") && (result.toLowerCase() == "wrong") ) result = "incorrect";

		doLMSSetValue("cmi.interactions." + n + ".id", name);
		doLMSSetValue("cmi.interactions." + n + ".type", type);
		doLMSSetValue("cmi.interactions." + n + ".student_response", response);
		doLMSSetValue("cmi.interactions." + n + ".correct_responses.0.pattern", pattern);
		doLMSSetValue("cmi.interactions." + n + ".result", result);

	}

}


/*******************************************************************************
** Purpose: Determine SCORM API version.
** Inputs: None.
** Returns: Nothing -- sets global variables.
**
** Created by J. Eckenrode, 2/2008
*******************************************************************************/
function getAPIversion() {

	var tries;
	var hWindow;

	//Check for SCORM 2004.
	tries = 0
	hWindow = window;
	while ( hWindow && (tries++ < 100) ) {

		if (hWindow.API_1484_11) {
			lmsConnected = true;
			SCORMversion = "2004";
			return;
		}

		hWindow = hWindow.parent;

	}

	//Check for SCORM 1.2.
	tries = 0
	hWindow = window;
	while ( hWindow && (tries++ < 100) ) {

		if (hWindow.API) {
			lmsConnected = true;
			SCORMversion = "1.2";
			return;
		}

		hWindow = hWindow.parent;

	}

	lmsConnected = false;
	SCORMversion = null;

}

