/**
 * Interlude de pré-chargement des images.
 * Permet de pré-charger des images dans le cache du navigateur,
 * tout en affichant une barre de progression animée pour distraire l'utilisateur pendant ce temps
 *
 * L'appel se fait via la méthode loadImages(container, array) qui prend le div à animer et un tableau d'URL en paramètre
 * et rend la main une fois le chargement terminé
 */
 
/**
  * Crée une instance de l'AnimatedLoader.
  * Il n'est par défaut associé à rien et peut donc resservir plusieurs fois.
  */  
function AnimatedLoader()
{
	this.loadedCount = 0;
	this.totalCount = 0;
	this.errorCount = 0;
	this.loadAborted = false;
	
	this.progressBar = 0;
	this.loadCompleted = false;
	this.loadInProgress = false;
}


AnimatedLoader.prototype = {

	/**
	  * Appel interne : création de l'animation
	  */
	createDHTMLAnimation : function(container) 
	{
		this.master = document.createElement('div');
			
		var background = document.createElement('div');
		background.setAttribute('class', 'progress_background');
		background.style.opacity=0.5;
		this.master.appendChild(background);
	
		var progressContainer = document.createElement('div');
		progressContainer.setAttribute('class', 'progress_container');
		this.master.appendChild(progressContainer);
		
		var progressArea = document.createElement('div');
		progressArea.setAttribute('class', 'progress_area');
		progressContainer.appendChild(progressArea);
		
		this.progressBar = document.createElement('div');
		this.progressBar.setAttribute('class', 'progress_bar');
		progressArea.appendChild(this.progressBar);
		
		this.barDeco1 = document.createElement('img');
		this.barDeco1.setAttribute('class', 'progressImage');
		this.barDeco1.setAttribute('src', 'base_images/progressFirst.png');
		this.progressBar.appendChild(this.barDeco1);
		this.barDeco2 = document.createElement('img');
		this.barDeco2.setAttribute('class', 'progressImage');
		this.barDeco2.setAttribute('src', 'base_images/progressSecond.png');
		this.progressBar.appendChild(this.barDeco2);
		
		this.progressValue = document.createElement('div');
		this.progressValue.setAttribute('class', 'progress_value');
		progressArea.appendChild(this.progressValue);

		var progressText = document.createElement('div');
		progressText.setAttribute('class', 'progress_text');
		var text = document.createTextNode("Chargement en cours");
		progressText.appendChild(text);
		progressArea.appendChild(progressText);
		
		container.appendChild(this.master);
		
		// variable globale, TODO : trouver une manière de s'en passer
		currentLoader = this;
		this.animationId = setInterval("AnimatedLoader.prototype.animate(currentLoader)", 100);
		this.animationTimer = 0;
		
		this.container = container;
	},
	
	/**
	  * Appel interne : nettoyage des élements d'animation
	  * En sortie, les pointeurs internes (container, progress bar) valent 0
	  */
	clearDHTMLAnimation : function()
	{
		clearInterval(this.animationId);
		this.container.removeChild(this.master);
		this.progressBar = 0;
		this.container = 0;
	},
	
	/**
	  * Animation : appelée de manière périodique
	  *  - change la transparence de la barre supérieure, laissant apparaître plus ou moins celle du dessous
	  *  - donne aux barres un mouvement de rebond
	  */
	animate : function (animation) {
		var height = [0, 0, 1, 1, 2, 3, 5, 8, 12, 8, 5, 3, 2, 1, 1, 0];
		var animationLoop = height.length;
		animation.barDeco1.style.top = height[(animation.animationTimer+1)%animationLoop];
		animation.barDeco2.style.top = height[animation.animationTimer%animationLoop];
		animation.barDeco2.style.opacity = 0.5-0.5*Math.cos(0.3*animation.animationTimer);
		animation.animationTimer++;
	},
	
	/**
	  * Charge les images 
	  *  container : div qui doit recevoir l'animation
	  *  sourceFileArray : tableau contenant les URL vers les images à charger
	  *  callback : méthode à appeler une fois le chargement terminé, ou abandonné
	  */
	loadImages : function(container, sourceFileArray, callback)
	{
		this.loadCompleted = false;
		this.loadInProgress = true;

		this.loadedCount = 0;
		this.totalCount = sourceFileArray.length;
		this.callback = callback;
		
		
		this.createDHTMLAnimation(container);
		
		for (var index=0; index<this.totalCount; ++index) {
			var currentImage = new Image;
			// évolution possible : récupérer les images chargées

			currentImage.onload = LoaderEventHandler.prototype.onLoad;
			currentImage.onerror = LoaderEventHandler.prototype.onError;
			currentImage.onabort = LoaderEventHandler.prototype.onAbort;
		    currentImage.loader = this;

			//alert(sourceFileArray[index]);
			currentImage.src = sourceFileArray[index];
		}
	},
	
	/** 
	  * Méthode appelée à chaque chargement, réussi, échoué, ou abandonné.
	  * Si toutes les images ont été chargées (avec éventuellement des erreurs), 
	  * ou s'il y a eu abondon, on nettoie les éléments d'animation, et on rappelle la callback.
	  */
	updateProgress : function()
	{
		var percentage = Math.floor(100*(this.loadedCount+this.errorCount)/this.totalCount);
		this.progressBar.style.width = percentage+"%";
		this.progressValue.innerHTML = percentage+"%"; 
		if (percentage == 100 || this.loadAborted) {
			this.clearDHTMLAnimation();
			this.loadCompleted = true;
			this.loadInProgress = false;
			if (this.callback) {
				this.callback(this.errorCount>0, this.loadAborted);
			}
		}
	}
}

/**
  *  LoaderEventHandler est un namespace gérant les événements sur les images chargées
  */
function LoaderEventHandler()
{
}

LoaderEventHandler.prototype = {

	onLoad : function() {
		++this.loader.loadedCount;
		this.loader.updateProgress();
	},
	
	onError : function() {
		++this.loader.errorCount;
		this.loader.updateProgress();
	},
	
	onAbort : function() {
		this.loader.loadAborted = true;
		this.loader.updateProgress();
	}
}
