/*******************************************************************************
** initialisations
*******************************************************************************/
var NB_MAX_SIZE_SUSPEND_DATA = 1000;

var bAPIBased = false; // flag : le tracking est-il APIBased ?
var bTrackInteractions = false; // flag : faut-il tracker les interactions ?
var aTrackInteractionsList = []; // liste des champs supportés par le LMS
var API = null; // objet API délivré par une des fenetres parentes
var nFindAPITries = 0;  // compteur de la profondeur de recherche de l'API dans la hierarchie des fenetres
/*******************************************************************************
** fonctions APIBased
*******************************************************************************/
function APIBased_LMSInitialize() {
	//alert("APIBased_LMSInitialize");
	API = getAPI(); // recherche de l'API
	if (API != null) {
		var sResult = API.LMSInitialize(""); //Peut renvoyer une chaine ou un booleen ou rien du tout
		if (sResult == null) sResult = false;
		sResult = sResult.toString();
		sResult = sResult.toLowerCase();
		bAPIBased = (sResult == "true"); //On est en mode APIBased si seulement LMSInitialize renvoit true ou "true" (indépendamment de la casse)
	}
	//trace("APIBased_LMSInitialize bAPIBased = " + bAPIBased);
	return bAPIBased;
}

function APIBased_LMSFinish() {
	//trace("APIBased_LMSFinish");
	var buffer = false;
	if(API != null) {
		// envoie de toutes les données stockées
		//trace("APIBased_LMSFinish sTrack_score = " + sTrack_score);
		//trace("APIBased_LMSFinish sTrack_session_time = " + sTrack_session_time);
		//trace("APIBased_LMSFinish sTrack_lesson_status = " + sTrack_lesson_status);
		//trace("APIBased_LMSFinish sTrack_lesson_location = " + sTrack_lesson_location);
		//trace("APIBased_LMSFinish sTrack_suspend_data = " + sTrack_suspend_data);
		API.LMSSetValue("cmi.core.score.raw", sTrack_score);
		API.LMSSetValue("cmi.core.session_time", sTrack_session_time);
		API.LMSSetValue("cmi.core.lesson_status", sTrack_lesson_status);
		API.LMSSetValue("cmi.core.lesson_location", sTrack_lesson_location);
		API.LMSSetValue("cmi.suspend_data", sTrack_suspend_data);
		API.LMSCommit("");
		// termine la session
		API.LMSFinish("");
		buffer = APIBased_LMSGetLastError();
		//trace("APIBased_LMSFinish LastError = " + buffer);
	}
	
	//alert("APIBased_LMSFinish");
	
	return buffer;
}

function APIBased_getLMSParameters() { // retourne des paramètres url_encoded avec des infos sur le tracking 
	var buffer = "";
	buffer  = buffer + "&bAPIBased=" + bAPIBased; // flag "API Based"
	if(bAPIBased) {
		sTrack_score = APIBased_LMSGetValue("cmi.core.score.raw");
		sTrack_session_time = "00:00:00";
		sTrack_lesson_status = APIBased_LMSGetValue("cmi.core.lesson_status");
		sTrack_lesson_location = APIBased_LMSGetValue("cmi.core.lesson_location");
		sTrack_suspend_data = APIBased_LMSGetValue("cmi.suspend_data");

		buffer  = buffer + "&sLessonLocation=" +  sTrack_lesson_location; // page de sortie
		buffer  = buffer + "&sLessonStatus=" + sTrack_lesson_status; // statut

		if(sTrack_suspend_data.length > NB_MAX_SIZE_SUSPEND_DATA) {
			// historique trop long pour être envoyé directement au swf en parametre (limitation IE)
			// le swf doit demander au javascript de lui envoyer en plusieurs fois
			buffer  = buffer + "&sSuspendData=" + "big";
		} else {
			buffer  = buffer + "&sSuspendData=" + sTrack_suspend_data; // historique
		}

		aTrackInteractionsList = APIBased_LMSGetValue("cmi.interactions._children").split(","); // si le LMS supporte les interactions, la fonction doit retourner la liste des champs supportés (exple : "id,result,type,weighting")
		bTrackInteractions = (aTrackInteractionsList.length > 0);
		buffer  = buffer + "&bTrackInteractions=" + bTrackInteractions; // flag "Track Interactions"
	}
	return buffer;
}

function sendSuspendDataToPlayer(sIndex) {
	// on découpe le suspend_data en bloc de NB_MAX_SIZE_SUSPEND_DATA caractères pour contourner la limitation de IE
	var nL = sTrack_suspend_data.length;
	var n = Math.floor((nL - 1)/NB_MAX_SIZE_SUSPEND_DATA) + 1;
	var nIndex = Number(sIndex);
	if(nIndex >= 0 && nIndex < n) {
		// on envoie le bloc nIndex
		setFlashVariable("sSuspendData", sTrack_suspend_data.substr(nIndex * NB_MAX_SIZE_SUSPEND_DATA, NB_MAX_SIZE_SUSPEND_DATA)); 
	} else {
		// on signale la fin de l'envoi
		setFlashVariable("sSuspendData", "stop"); 
	}
}

function isValueInArray(aArray, sValue) {
	var buffer = false;
	var i = 0;
	var n = aArray.length;
	while(i < n && !buffer) {
		buffer = (aArray[i] == sValue);
		i++;
	}
	return buffer; 
}

function getInteractionName(sElement) {
	var aList = sElement.split(".");
	return aList[aList.length - 1]; 
}

function APIBased_LMSSetValue(sElement, sValue, bIsInteraction) {
	if(API != null) {
		if(!bIsInteraction) {
			API.LMSSetValue(sElement, sValue);
			API.LMSCommit(""); // on commit pour être sûr que le LMS stocke la valeur (certains LMS ont besoin de ceci pour réellement stocker la valeur)
		} else { // interaction : on vérifie que l'interaction est supportée par le LMS
			// exple : cmi.interactions.1.correct_response_text
			if(isValueInArray(aTrackInteractionsList, getInteractionName(sElement))) {
				API.LMSSetValue(sElement, sValue); // on n'envoie l'interaction que si elle est supportée par le LMS
				API.LMSCommit("");
			}
		}
	}
}

function APIBased_LMSGetValue(sElement) {
	var buffer = "";
	if(API != null) buffer = API.LMSGetValue(sElement);
	return buffer;
}
function APIBased_LMSGetLastError() {
	var buffer = true;
	if(API != null) buffer = API.LMSGetLastError();
	return buffer;
}
/*******************************************************************************
**
** Function findAPI(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 parent and opener windows
**
*******************************************************************************/
function findAPI(win) {
   while ((win.API == null) && (win.parent != null) && (win.parent != win))
   {
      nFindAPITries++;
      // Note: 500 is a number that comes from the new IEEE API standard.
      //       See rational in ticket number 3547
      if (nFindAPITries > 500) {
         //alert("Error finding API -- too deeply nested.");
         return null;
      }
      win = win.parent;
   }
   return win.API;
}
/*******************************************************************************
**
** 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
** frame hierarchy and then, if necessary, in the current window's opener window
** hierarchy (if there is an opener window).
**
*******************************************************************************/
function getAPI() {
   theAPI = findAPI(window);
   
   // Avec frame
   if ((theAPI == null) && (window.parent.opener != null) && (typeof(window.parent.opener) != "undefined")) {
	   theAPI = findAPI(window.parent.opener);
	   if ((theAPI == null) && (window.parent.opener.opener != null) && (typeof(window.parent.opener.opener) != "undefined")) {
		   theAPI = findAPI(window.parent.opener.opener);
	   }
   }

   if (theAPI == null)   {
      //alert("Unable to find an API adapter");
   }
   return theAPI;
}