// SHIM ////////////////////////////////////////////////////////////////////////

function apishim(realapi) { 
	this.api = realapi;
	
	this.LMSInitialize = function(parameter) {
		var result = this.api.LMSInitialize(parameter);

		if(result == "true") {
			setup_scorm_time_tracking(this); 
		}
		
		return result;
	}
	
	this.LMSFinish = function(parameter) {
		finish_scorm_time_tracking(this);

		var result = this.api.LMSFinish(parameter);
		return result;
	}
	
	this.LMSGetValue = function(parameter) {
		var result = this.api.LMSGetValue(parameter);

		return result;
	}
	
	this.LMSSetValue = function(parameter, value) {
		var result = this.api.LMSSetValue(parameter, value);

		return result;
	}
	
	this.LMSCommit = function(parameter) {
		var result = this.api.LMSCommit(parameter);

		return result;
	}
	
	this.LMSGetLastError = function() {
		var result = this.api.LMSGetLastError();

		return result;
	}
	
	this.LMSGetErrorString = function(errornumber) {
		var result = this.api.LMSGetErrorString(errornumber);

		return result;
	}
	
	this.LMSGetDiagnostic = function(parameter) {
		var result = this.api.LMSGetDiagnostic(parameter);

		return result;
	}
}

// SHIM GETTER /////////////////////////////////////////////////////////////////

function getAPI() {
	var theAPI = getRealAPI();
	
	if(theAPI == null) {
		return theAPI;
	}
	
	return new apishim(theAPI);
}

// OLD APIADAPTER //////////////////////////////////////////////////////////////

var findAPITries = 0;
var __MAX_API_SEEK_DEPTH = 7;

function findAPI(win) {
	while((null == win.API) && (null != win.parent) && (win.parent != win)) {
		findAPITries++;

		if(findAPITries > __MAX_API_SEEK_DEPTH) {
			win.status = "Error finding API -- too deeply nested.";
			return null;
		}

		win = win.parent;
	}

	return win.API;
}

function getRealAPI() {
	var theAPI = findAPI(window);

	if(null == theAPI && null != window.parent) {
		var theAPI = findAPI(window.parent);
	}

	if((null == theAPI) && (null != window.parent.opener) && ("undefined" != typeof(window.parent.opener))) {
		var theAPI = findAPI(window.parent.opener);
	}

	if((null == theAPI) && (null != window.opener) && ("undefined" != typeof(window.opener))) {
		theAPI = findAPI(window.opener);
	}

	if(null == theAPI) {
		window.status = "Unable to find an API adapter.";
	}

	return theAPI;
}

// TIME RELATED ////////////////////////////////////////////////////////////////

var __api_initialized_time = new Date().getTime();
var __can_track_time = false;

function setup_scorm_time_tracking(api) {
	var corechildren = api.LMSGetValue("cmi.core._children");
	if(corechildren.indexOf('session_time') != -1) {
		__can_track_time = true;

		// Start tracking time
		__api_initialized_time = new Date().getTime();
	}
}

function finish_scorm_time_tracking(api) {
	if(__can_track_time) {
		api.LMSSetValue('cmi.core.session_time', get_scorm_api_time_differences());
		api.LMSCommit('');
	}
}

function get_scorm_api_time_differences() {
	var rightnow = new Date().getTime();
    var diff = new Date();
    diff.setTime(Math.abs(__api_initialized_time - rightnow));
    var timediff = diff.getTime();
	
	var dn = 0;

	dn = (1000 * 60 * 60);
	var hours = Math.floor(timediff / dn);
	timediff -= hours * dn;
	
	dn = (1000 * 60);
	var mins = Math.floor(timediff / dn);
	timediff -= mins * dn;
	
	dn = 1000;
	var secs = Math.floor(timediff / dn);
	timediff -= secs * dn;
	
	hours = padstr(hours.toString(), '0', 2);
	mins = padstr(mins.toString(), '0', 2);
	secs = padstr(secs.toString(), '0', 2);
	
    return hours + ':' + mins + ':' + secs;
}

function padstr(what, padwith, howmany) {
	padding = '';
	what = what.toString();
	for(i = what.length; i < howmany; i++) { padding = padding + padwith; }
	return padding + what;
}