/***************************************************************************
**
** Advanced Distributed Learning Co-Laboratory (ADL Co-Lab) 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 ADL Co-Lab.
**
** 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.  ADL Co-Lab 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 ADL Co-Lab 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 ADL Co-Lab HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
** DAMAGES.
**
***************************************************************************/

/*******************************************************************************
**
** Function findAPI_12(win)
** Inputs:  win - a Window Object
** Return:  If an API object is found, it's returned, otherwise null is returned
**
** Description:
** This function looks for an object named API in the supported window hierarchy 
** 
*******************************************************************************/

var _Debug = false;

function findAPI_12(win) 
{

   // Search the window hierarchy for an object named "API"  
   // Look in the current window (win) and recursively look in any child frames


   if (_Debug)
   {
      alert("win is: "+win.location.href);
   }


   if (win.API != null)
   {
      if (_Debug)
      {
         alert("found api in this window");
      }
      return win.API;
   }

   if (win.length > 0)  // does the window have frames?
   {
      if (_Debug)
      {
         alert("looking for api in windows frames");
      }

      for (var i=0;i<win.length;i++)
      {

         if (_Debug)
         {
            alert("looking for api in frames["+i+"]");
         }
         var theAPI = findAPI_12(win.frames[i]);
         if (theAPI != null)
         {
            return theAPI;
         }
      }
   }

   if (_Debug)
   {
      alert("didn't find api in this window (or its children)");
   }
   return null;

}


/*******************************************************************************
**
** Function getAPI()
** Inputs:  none
** Return:  If an API object is found, it's returned, otherwise null is returned
**
** Description:
** This function looks for an object named API, first in the current window's 
** hierarchy, and then, if necessary, in the current window's opener window 
** hierarchy (if there is an opener window).
*******************************************************************************/
function getAPI_12()
{
   if (_Debug)
   {
      alert("in getAPI()");
   }

   // start at the topmost window - findAPI will recurse down through
   // all of the child frames
   var theAPI = findAPI_12(this.top);

   if (theAPI == null)
   {
      // the API wasn't found in the current window's hierarchy.  If the
      // current window has an opener (was launched by another window),
      // check the opener's window hierarchy. 
      if (_Debug)
      {
         alert("checking to see if this window has an opener");
         alert("window.opener typeof is> "+typeof(window.opener));
      }

      if (typeof(top.opener) != "undefined")
      {
         if (_Debug)
         {
            alert("checking this windows opener");
         }
         if (top.opener != null)
         {
            if (_Debug)
            {
               alert("this windows opener is NOT null - looking there");
            }
            theAPI = findAPI_12(top.opener.top);
         }
         else
         {
            if (_Debug)
            {
               alert("this windows opener is null");
            }
         }
      }
   }

   return theAPI;
}

// #################### End ADL Co-Lab Licensed Code ###################

// #################### Local API Functions ############################

function LocalAPI(config) {
	this.config = config;
	this._data_elements = null;
	this.__inited__ = false;
}

function localLMSInitialize(parameter) {
	this._data_elements = this._unpickle();
	this.__inited__ = true;
	return true;
}

function localLMSFinish(parameter) {
	this.__inited__ = false;
	return true;
}

function localLMSGetValue(data_element) {
	if (!this.__inited__ || !this._data_elements || !data_element) { return ''; }
	
	if (this._data_elements[data_element]) {
		return this._data_elements[data_element];
	}
	return '';
}

function localLMSSetValue(data_element, value) {

	if (!this.__inited__ || !this._data_elements || !data_element) { return false; }
	if (data_element != null) {
		this._data_elements[data_element] = value;
	}
	return true;
}

function localLMSCommit(parameter) {

	if (!this.__inited__) { return false; }

	this._pickle(this._data_elements);
	return true;
}

// #################### Local API Storage Impl ############################

function LocalAPIPickleImpl(obj) {
	var pickle = new Cookie(document,this.config.name,this.config.lifetime,'/');
	for (var o in obj) {
		pickle[o] = obj[o];
	}
	pickle.store();
}

function LocalAPIUnpickleImpl() {
	var pickle = new Cookie(document,this.config.name,this.config.lifetime,'/');
	pickle.load();
	var obj = new Object();
	for (var o in pickle) {
		if ((o.charAt(0) != '$') && ((typeof pickle[o]) != 'function')) { obj[o] = pickle[o]; }
	}
	return obj;
}

// #################### Local API Prototypes ############################

LocalAPI.prototype.LMSInitialize = localLMSInitialize;
LocalAPI.prototype.LMSFinish = localLMSFinish;
LocalAPI.prototype.LMSGetValue = localLMSGetValue;
LocalAPI.prototype.LMSSetValue = localLMSSetValue;
LocalAPI.prototype.LMSCommit = localLMSCommit;
LocalAPI.prototype.LMSGetErrorString = function() { return 'No Error'; }
LocalAPI.prototype.LMSGetDiagnostic = function() { return 'The previous LMS API Function call completed successfully.'; }
LocalAPI.prototype.LMSGetLastError = function() { return 0; }

LocalAPI.prototype._pickle = LocalAPIPickleImpl;
LocalAPI.prototype._unpickle = LocalAPIUnpickleImpl;


// #################### Applet API Functions ############################

function AppletAPI(appletref,web_launch) {
	this.appletref = appletref;
	if (web_launch) { this.web_launch = web_launch; } else { this.web_launch = ''; }
	this.ready = false;
}

function AppletLMSInitialize(parameter) {
	this.ready = true;
	return true;
}

function AppletLMSFinish(parameter) {
	if (!this.ready) { return false; }
	this.ready = false;
	this.appletref.ExitAU();
	return true;
}

function AppletLMSGetValue(data_element) {
	if (!this.ready || !data_element) { return ''; }

	if (eval(data_element)) {
		return eval(data_element)(this);
	}
	return '';

}

function AppletLMSSetValue(data_element, value) {
	if (!this.ready || !data_element) { return false; }
	
	if (eval(data_element)) {
		eval(data_element)(this,value);
	}
	
	return true;

}

function AppletLMSCommit(parameter) {
	return true;
}

// #################### Applet API Storage Impl ############################

function AICCImplFactory(group,name) {
	var element_factory = function(self,value) {
		var appletref = self.appletref;
		if (value != null) {
			if (name) {
				appletref.PutParam(group,name,value);
			} else {
				appletref.PutParam(group,value);
			}
		} else {
			var getparam = appletref.GetParam(group,name);
			return getparam;
		}
	}
	
	return element_factory;
	
}

function AICCLaunchData(self,value) { 
	if (value == null) {
		return self.web_launch;
	}
}

var cmi=new Object();
cmi.core = new Object();
cmi.core.student_id = AICCImplFactory('[core]','student_id');
cmi.core.student_name = AICCImplFactory('[core]','student_name');
cmi.core.lesson_location = AICCImplFactory('[core]','lesson_location');
cmi.core.lesson_status = AICCImplFactory('[core]','lesson_status');
cmi.core.credit = AICCImplFactory('[core]','credit');
cmi.core.score = new Object();
cmi.core.score.raw = AICCImplFactory('[core]','score');
cmi.core.time = AICCImplFactory('[core]','time');
cmi.suspend_data = AICCImplFactory('[core_lesson]',null);
cmi.launch_data = AICCLaunchData;



// #################### Applet API Prototypes ############################

AppletAPI.prototype.LMSInitialize = AppletLMSInitialize;
AppletAPI.prototype.LMSFinish = AppletLMSFinish;
AppletAPI.prototype.LMSGetValue = AppletLMSGetValue;
AppletAPI.prototype.LMSSetValue = AppletLMSSetValue;
AppletAPI.prototype.LMSCommit = AppletLMSCommit;
AppletAPI.prototype.LMSGetErrorString = function() { return 'No Error'; }
AppletAPI.prototype.LMSGetDiagnostic = function() { return 'The previous LMS API Function call completed successfully.'; }
AppletAPI.prototype.LMSGetLastError = function() { return 0; }

// #################### Debug API Functions ############################

function DebugAPI(API) {
	this.API = API;
	var debugwin = window.open("about:blank","debugwin","location=no,menubar=no,scrollbars=yes");
	this.console = new Console(debugwin);
}

function debugLMSInitialize(parameter) {
	var initialize = this.API.LMSInitialize(parameter);
	this.console.writeln("LMSInitialize('" + parameter + "') = " + initialize);
	this.debugDump();
	return initialize;
}

function debugLMSFinish(parameter) {
	var finish = this.API.LMSFinish(parameter);
	this.console.writeln("LMSFinish('" + parameter + "') = " + finish);
	this.debugDump();	
	return finish;
}

function debugLMSGetValue(data_element) {
	var value = this.API.LMSGetValue(data_element);
	this.console.writeln("LMSGetValue('" + data_element + "') = " + value);
	this.debugDump();
	return value;
}

function debugLMSSetValue(data_element, value) {
	var setvalue = this.API.LMSSetValue(data_element, value);
	this.console.writeln("LMSSetValue('" + data_element + "','" + value + "') = " + setvalue);
	this.debugDump();
	return setvalue;
}

function debugLMSCommit(parameter) {
	var commit = this.API.LMSCommit(parameter);
	this.console.writeln("LMSCommit('" + parameter + "') = " + commit);
	this.debugDump();
	return commit;
}

function debugLMSGetErrorString(parameter) {
	var errorstr = this.API.LMSGetErrorString(parameter);
	this.console.writeln("LMSGetErrorString('" + parameter + "') = " + errorstr);
	return errorstr;
}

function debugLMSGetDiagnostic(parameter) {
	var diag = this.API.LMSGetDiagnostic(parameter);
	this.console.writeln("LMSGetDiagnostic('" + parameter + "') = " + diag);
	return diag;
}

function debugLMSGetLastError() {
	var lasterr = this.API.LMSGetLastError();
	this.console.writeln("LMSGetLastError() = " + lasterr);
	return lasterr;
}

function debugDump() {
	var lasterr = this.LMSGetLastError();
	var lasterrstr = this.LMSGetErrorString(lasterr);
	var lasterrdiag = this.LMSGetDiagnostic(lasterr);
	this.console.writeln("---------------");
}

// #####

function Console(win) {
	this.win = win;
	win.document.open("text/plain");
}

Console.prototype.writeln = function(text) {
	if (this.win && !this.win.closed) {
		this.win.document.writeln(text);
	}
}

// #################### Debug API Prototypes ############################

DebugAPI.prototype.LMSInitialize = debugLMSInitialize;
DebugAPI.prototype.LMSFinish = debugLMSFinish;
DebugAPI.prototype.LMSGetValue = debugLMSGetValue;
DebugAPI.prototype.LMSSetValue = debugLMSSetValue;
DebugAPI.prototype.LMSCommit = debugLMSCommit;
DebugAPI.prototype.LMSGetErrorString = debugLMSGetErrorString;
DebugAPI.prototype.LMSGetDiagnostic = debugLMSGetDiagnostic;
DebugAPI.prototype.LMSGetLastError = debugLMSGetLastError;
DebugAPI.prototype.debugDump = debugDump;

// #################### Checked API Functions ############################

function CheckedAPI(API) {
	this.API = API;
	this.__inited__ = false;
}

function CheckedLMSInitialize(parameter) {
	var initialize = this.API.LMSInitialize(parameter);
	if (initialize) { this.__inited__ = true; }
	return initialize;
}

function CheckedLMSFinish(parameter) {
	this.__inited__ = false;
	var finish = this.API.LMSFinish(parameter);
	return finish;
}

function CheckedLMSGetValue(data_element) {
	var value = this.API.LMSGetValue(data_element);
	return value;
}

function CheckedLMSSetValue(data_element, value) {
	var setvalue = this.API.LMSSetValue(data_element, value);
	return setvalue;
}

function CheckedLMSCommit(parameter) {
	var commit = this.API.LMSCommit(parameter);
	return commit;
}

function CheckedLMSGetErrorString(parameter) {
	var errorstr = this.API.LMSGetErrorString(parameter);
	return errorstr;
}

function CheckedLMSGetDiagnostic(parameter) {
	var diag = this.API.LMSGetDiagnostic(parameter);
	return diag;
}

function CheckedLMSGetLastError() {
	var lasterr = this.API.LMSGetLastError();
	return lasterr;
}

// #################### Checked API Prototypes ############################

CheckedAPI.prototype.LMSInitialize = CheckedLMSInitialize;
CheckedAPI.prototype.LMSFinish = CheckedLMSFinish;
CheckedAPI.prototype.LMSGetValue = CheckedLMSGetValue;
CheckedAPI.prototype.LMSSetValue = CheckedLMSSetValue;
CheckedAPI.prototype.LMSCommit = CheckedLMSCommit;
CheckedAPI.prototype.LMSGetErrorString = CheckedLMSGetErrorString;
CheckedAPI.prototype.LMSGetDiagnostic = CheckedLMSGetDiagnostic;
CheckedAPI.prototype.LMSGetLastError = CheckedLMSGetLastError;

// #################### Wrapped 2004 API Functions ############################

 /**************************************************************************
**
** Function: API Object
** Inputs:  Catch all for 1.2 SCO calls
** Return:  none
**
** Description:
** APIObject is a JavaScript Object that acts as the SCORM 1.2 api and is
** used to catch all the SCORM 1.2 calls prior to sending the calls onto
** the LMS.
**
**************************************************************************/ 
function APIObject()
{
   this.LMSInitialize = LMSInitialize;
   this.LMSFinish = LMSFinish;
   this.LMSGetValue = LMSGetValue;
   this.LMSSetValue = LMSSetValue;
   this.LMSCommit = LMSCommit;
   this.LMSGetLastError = LMSGetLastError;
   this.LMSGetErrorString = LMSGetErrorString;
   this.LMSGetDiagnostic = LMSGetDiagnostic;  
}

/**************************************************************************
**
** Function: LMSInitialize()
** Inputs:  None
** Return:  A string indicating whether or not the function completed 
**          successfully (true or false)
**
** Description:
** Initialize communication with LMS by calling the Initialize
** function which will be implemented by the LMS. The result is returned
** by the SCOPlayerWrapper.js file.
**
**************************************************************************/
function LMSInitialize()
{
   // CALL INITIALIZE
   result = doLMSInitialize();
   if(result)
	{
	   this.__inited__ = true;
	}
   return result.toString(); 
}

/**************************************************************************
**
** Function: LMSFinish()
** Inputs:  None
** Return:  A string indicating whether or not the function completed 
**          successfully (true or false)
**
** Description:
** LMSFinish comunicates with the LMS via SCOPlayerWrapper, converting the 
** LMSFinish call to Terminate and passing on to the LMS.
**
**************************************************************************/    
function LMSFinish()
{
   // CALL TERMINATE
   result = doLMSFinish();
   if(result)
	{
	   this.__inited__ = false;
	}
   return result.toString();
}

/**************************************************************************
**
** Function: LMSGetValue()
** Inputs:  Name of Element to retrieve
** Return:  Result of the getValue call 
**
** Description:
** This funciton takes in the name of the element that is attempting to be 
** set, passes the element along to the SCOPlayerWrapper.js and in return 
** the SCOPlayerWrapper.js file returns the appropriate SCORM 1.2 conformant
** value. 
**
**************************************************************************/    
function LMSGetValue(name)
{
   result = doLMSGetValue(name);
   return result.toString();
}

/**************************************************************************
**
** Function: LMSSetValue()
** Inputs:  Element name and value to set it to
** Return:  A string indicating whether or not the function completed 
**          successfully (true or false)
**
** Description:
** LMSSetValue accepts the value and element name to set, passing them on
** to doLMSSetValue within SCOPlayerWrapper.js to complete the conversion
** process communicating with the SCORM 2004 LMS.
**
***************************************************************************/    
function LMSSetValue(name, value)
{
   result = doLMSSetValue(name, value);
   return result.toString();
}

/**************************************************************************
**
** Function: LMSCommit()
** Inputs:  None
** Return:  A string indicating whether or not the function completed 
**          successfully (true or false)
**
** Description:
** LMSCommit calls doLMSCommit within SCOPlayerWrapper.js file passing the 
** call on to the SCORM 2004 LMS.
**
***************************************************************************/    
function LMSCommit()
{
   var result = doLMSCommit();
   return result.toString();
}

/***************************************************************************
**
** Function doLMSGetLastError()
** Inputs:  None
** Return:  The error code that was set by the last LMS function call
**
** Description:
** Calls the doLMSGetLastError function, located in SCOPlayerWrapper.js
** which converts the SCORM 2004 error code provided by the LMS to 
** SCORM 1.2. 
**
***************************************************************************/
function LMSGetLastError()
{
   if ( _InternalErrCode == 1 )
   {
	  // There is no error the APIWrapper caught the last call and did not
	  // comunicate with the LMS
	  return 0;
   }
   else
   {
	  errorcode12 = doLMSGetLastError();
	  return errorcode12;
   }
}

/***************************************************************************
**
** Function doLMSGetErrorString(errorCode)
** Inputs:  errorCode - Error Code
** Return:  The textual description that corresponds to the input error code
**
** Description:
** Calls doLMSGetErrorString function located within SCOPlayerWrapper.js. 
**
***************************************************************************/
function LMSGetErrorString(errorCode)
{
   var errString = doLMSGetErrorString(errorCode);
   return errString;
}

/***************************************************************************
**
** Function doLMSGetDiagnostic(errorCode)
** Inputs:  errorCode - Error Code(integer format), or null
** Return:  The vendor specific textual description that corresponds to the 
**          input error code
**
** Description:
** Calls doLMSGetDiagnostic function located within SCOPlayerWrapper.js.n
**
***************************************************************************/
function LMSGetDiagnostic(errorCode)
{
   var errString = getErrorString(errorCode);
   return errString;
}

