
/**
 * Constructeur du carrousel
 * 
 * @param string idImgsContainer		Id du conteneur des images
 * @param string idImgActuContainer		Id du conteneur pour afficher le nom de l'image actuelle (alt)
 * @param string idLiensContainer		Id du conteneur des liens (pour changer d'image)
 * @param int speedCarrousel			Vitesse de défilement du carrousel (entre chaque image). Exprimé en millisecondes
 * @param int speedFadding				[Optionnel] Vitesse de la transition en fondu. Exprimé en millisecondes. Si non saisi, aucun fondu.
 * @param object options				[Optionnel] Options éventuelles de configuration avancée du carrousel 
 */
function RSPlug_Carrousel (idImgsContainer, idImgActuContainer, idLiensContainer, speedCarrousel, speedFadding, options){
	// Mise à zéro des variables
	this.lastImg = null;					// Dernière image vue (pour gérer le display: none)
	
	// Préparation de l'objet de configuration
	this.config = {
		setImgsContainerPosition: true,		// On force le position: relative car on place les images en absolute dedans
		startImgIndex: 0,					// Index de l'image de démarrage du carrousel
		waitEndFaddingBeforeChange: false,	// Doit-on attendre la fin du fondu avant de pouvoir changer d'image ?
		percentFaddingToChangeLink: 50,		// Pourcentage à atteindre pour changer le lien de l'image actuelle
		useFaddingToChange: false,			// Doit-on utiliser le fondu (si fondu) lorsqu'on change d'image via un clic ?
		changeImgCallback: null,			// Callback a appeler lorsqu'on commence le changement de l'image
		finishImgCallback: null				// Callback a appeler lorsqu'on termine le changement de l'image
	};
	if (options){
		if (null !== options.setImgsContainerPosition && !options.setImgsContainerPosition){
			this.config.setImgsContainerPosition = false;
		}
		if (null !== options.startImgIndex && options.startImgIndex > 0 && !isNaN(options.startImgIndex)){
			this.config.startImgIndex = parseInt(options.startImgIndex);
		}
		if (null !== options.waitEndFaddingBeforeChange && options.waitEndFaddingBeforeChange){
			this.config.waitEndFaddingBeforeChange = true;
		}
		if (null !== options.percentFaddingToChangeLink && options.percentFaddingToChangeLink >= 0 && options.percentFaddingToChangeLink <= 100 && !isNaN(options.percentFaddingToChangeLink)){
			this.config.percentFaddingToChangeLink = parseInt(options.percentFaddingToChangeLink);
		}
		if (null !== options.useFaddingToChange && options.useFaddingToChange){
			this.config.useFaddingToChange = true;
		}
		if (null !== options.changeImgCallback && options.changeImgCallback){
			this.config.changeImgCallback = options.changeImgCallback;
		}
		if (null !== options.finishImgCallback && options.finishImgCallback){
			this.config.finishImgCallback = options.finishImgCallback;
		}
	}
	
	// Récupération des conteneurs
	this.imgsContainer = document.getElementById(idImgsContainer);
	this.imgActuContainer = document.getElementById(idImgActuContainer);
	this.liensContainer = document.getElementById(idLiensContainer);
	
	// Défilement du carrousel
	this.toCarrousel = null;				// Timeout de défilement du carrousel
	this.speedCarrousel = speedCarrousel;	// Vitesse de défilement du carrousel (en millisecondes)
	
	// Fondu du carrousel
	if (speedFadding && !isNaN(speedFadding) && speedFadding > 0){
		this.speedFadding = parseFloat(speedFadding / 100);
		this.timeoutsFadding = [];			// Timeouts de l'effet de fondu
		this.useFadding = true;				// Utilise t-on l'effet de fondu ?
	} else {
		this.useFadding = false;			// Utilise t-on l'effet de fondu ?
	}
	this.fadding = false;					// Témoin de l'état de l'effet de fondu (un fondu est-il en court)
	
	// Récupération des images du carrousel + Mise en forme de ces dernières
	this.imgs = this.imgsContainer.getElementsByTagName('img');
	if (this.imgs.length == 0){
		return false;
	}
	if (this.config.startImgIndex < 0 || this.config.startImgIndex >= this.imgs.length){
		this.config.startImgIndex = 0;
	}
	if (this.config.setImgsContainerPosition){ 
		this.imgsContainer.style.position = 'relative';	
	}
	if (this.imgs.length > 1){
		for (var i=0; i<this.imgs.length; i++){
			this.imgs[i].style.position = 'absolute';
			this.imgs[i].style.left = 0;
			this.imgs[i].style.top = 0;
			this.imgs[i].style.display = 'none';
		}
		this.show(this.config.startImgIndex);
	}
}

/**
 * Fonction d'affichage d'une image du carrousel (sans fondu)
 */
RSPlug_Carrousel.prototype.show = function (imgIndex){
	if (this.fadding){
		return false;
	}
	if (null !== this.toCarrousel){
		clearTimeout(this.toCarrousel);
	}
	
	this.imgs[imgIndex].style.display = '';
	this.lastImg = this.imgs[imgIndex];
	this.imgActuContainer.innerHTML = this.imgs[imgIndex].alt.replace(/\|\|/g, '<br />');
	this.liensContainer.innerHTML = '';
	for (var i=0; i<this.imgs.length; i++){
		this.liensContainer.appendChild(this.createLink(i, (i == imgIndex)));
	}
	
	this.prepareNext (imgIndex);
};

/**
 * Fonction qui gère le défilement du carrousel (avec ou sans fondu)
 */
RSPlug_Carrousel.prototype.prepareNext = function (imgIndex){
	if (this.imgs.length > 1){
		var next = (imgIndex +1 < this.imgs.length) ? imgIndex +1: 0;
		var inst = this;
		if (this.useFadding){
			this.toCarrousel = setTimeout(function (){ inst.toCarrousel = null; inst.fadeTo(next); }, this.speedCarrousel);
		} else {
			this.toCarrousel = setTimeout(function (){ inst.toCarrousel = null; inst.goTo(next); }, this.speedCarrousel);
		}
	}
};

/**
 * Fonction qui crée les liens de numéro d'image
 */
RSPlug_Carrousel.prototype.createLink = function (imgIndex, actif){
	var link = document.createElement('a');
	link.href = '#';
	var inst = this;
	if (this.config.useFaddingToChange && this.useFadding){
		link.onclick = function(){
			if (null !== inst.toCarrousel){
				clearTimeout(inst.toCarrousel);
				inst.toCarrousel = null;
			}
			inst.clearFadding();
			inst.fadeTo(imgIndex);
			return false;
		};
	} else {
		link.onclick = function(){
			inst.goTo(imgIndex);
			return false;
		};
	}
	if (actif){
		link.className = 'actif';
	}
	link.innerHTML = this.imgs[imgIndex].alt.replace(/\|\|/g, ' ') + ' <strong>' + (imgIndex +1) + '</strong>';
	return link;
};

/**
 * Fonction pour se rendre à une image par son index, sans fondu
 */
RSPlug_Carrousel.prototype.goTo = function (imgIndex){
	if (this.fadding){
		if (this.config.waitEndFaddingBeforeChange){
			return false;
		}
		this.clearFadding();
	}
	if (null !== this.config.changeImgCallback){
		this.config.changeImgCallback(this);
	}
	if (null !== this.lastImg){
		this.lastImg.style.display = 'none';
	}
	this.show(imgIndex);
	if (null !== this.config.finishImgCallback){
		this.config.finishImgCallback(this);
	}
};

/**
 * Fonction pour se rendre à une image par son index, avec fondu
 */
RSPlug_Carrousel.prototype.fadeTo = function (imgIndex){
	this.fadding = true;
	this.timeoutsFadding = [];

	this.setOpacity(this.imgs[imgIndex], 0);
	this.imgs[imgIndex].style.display = '';
	
	var inst = this;
	var index = imgIndex;
	
	var selectImgNumber = function(){
		inst.imgActuContainer.innerHTML = inst.imgs[index].alt.replace(/\|\|/g, '<br />');
		inst.liensContainer.innerHTML = '';
		for (var i=0; i<inst.imgs.length; i++){
			inst.liensContainer.appendChild(inst.createLink(i, (i == index)));
		}
	};

	if (null !== this.config.changeImgCallback){
		this.config.changeImgCallback(this);
	}
	
	for (var i=0; i<=100; i++){
		var delai = this.speedFadding *i;
		this.timeoutsFadding.push(this.setFadding(this.lastImg, (100 -i), delai));
		this.timeoutsFadding.push(this.setFadding(this.imgs[imgIndex], i, delai));
		if (i == this.config.percentFaddingToChangeLink){
			this.timeoutsFadding.push(setTimeout(selectImgNumber, delai));
		}
	}
	
	var cleaner = function (){
		if (null !== inst.lastImg){
			inst.lastImg.style.display = 'none';
			inst.setOpacity(inst.lastImg, 100);
		}
		inst.imgs[index].style.display = '';
		inst.lastImg = inst.imgs[index];
		inst.prepareNext (index);
		inst.fadding = false;

		if (null !== inst.config.finishImgCallback){
			inst.config.finishImgCallback(inst);
		}
	};
	this.timeoutsFadding.push(setTimeout(cleaner, delai));
};

/**
 * Fonction pour interrompre le fondu (pour changer d'image par exemple)
 */
RSPlug_Carrousel.prototype.clearFadding = function(){
	if (this.useFadding){
		for (var i=0; i<this.timeoutsFadding.length; i++){
			if (this.timeoutsFadding[i]){
				clearTimeout(this.timeoutsFadding[i]);
			}
		}
		if (null !== this.lastImg){
			for (var i=0; i<this.imgs.length; i++){
				this.imgs[i].style.display = 'none';
				this.setOpacity(this.imgs[i], 100);
			}
		}
		this.fadding = false;
	}
};

/**
 * Fonction de déclaration du fondu
 */
RSPlug_Carrousel.prototype.setFadding = function (obj, opacity, delai){
	var inst = this;
	return setTimeout(function(){ inst.setOpacity(obj, opacity); }, delai);
};

/**
 * Fonction de déclaration d'opacité (multi-navigateur)
 */
RSPlug_Carrousel.prototype.setOpacity = function (obj, opak){
	if (obj && obj.style){
		opak = parseInt(opak);
		obj.style.opacity = (opak / 100);
		obj.style.MozOpacity = (opak / 100);
		obj.style.KhtmlOpacity = (opak / 100);
		obj.style.filter = 'alpha(opacity=' + opak + ')';
	}
};


