/**********************************************************************
*	
*	version du 09/10/2008
*	
*	Classe principale de fondu
*	
*	new Fondu() : nouveau fondu
*
*	parametres :
*	{
*		- idElement : identifiant de l'element dont on change l'opacite
*		- delai : temps de pause en millisecondes avant le debut du fondu
*		- nbIterations : nombre d'etapes entre le debut et la fin
*		- intervalle : temps de pause en millisecondes entre chaque etape
*		- onStart : fonction executee avant la premiere etape
*		- onFinish : fonction executee apres la derniere etape
*		- typeFondu : type de fondu (propriétés de Fondu.types)
*	}
*	
**********************************************************************/

function Fondu()
{
	this.parametres = {
		idElement: "",
		delai: 0,
		nbIterations: 10,
		intervalle: 25,
		onStart: null,
		onFinish: null,
		typeFondu: Fondu.types.continu
	};
	this.timer = null;
	this.i = 1;
	var thisObject = this;
	
	/*
	*	this.optionsDefaut()
	*	permet de tenir compte des parametres fournis tout en gardant les valeurs
	*	par defaut des parametres non fournis
	*
	*	- parametres : parametres founis
	*	
	*	note : les parametres par defaut sont this.parametres
	*/
	this.optionsDefaut = function(parametres)
	{
		if (parametres)
		{
			for (var propriete in parametres)
				this.parametres[propriete] = parametres[propriete];
		}
		return true;
	}
	
	/*
	*	this.getElement()
	*	initialise this.element
	*/
	this.getElement = function()
	{
		this.element = document.getElementById(this.parametres.idElement);
	}
	
	/*
	*	this.getIteration()
	*	retourne le coefficient correspondant a l'iteration en fonction du type de fondu
	*
	*	- i : numero de l'iteration, de 1 au nombre d'iterations
	*/
	this.getRapportIteration = function(i)
	{
		var rapport = i / this.parametres.nbIterations;
		var PIsur2 = Math.PI / 2;
		switch(this.parametres.typeFondu)
		{
			case Fondu.types.rebondsArrivee:
				var nombreRebonds = 3;
				var hauteurRebond = Math.cos(PIsur2 * (rapport + 1)) + 1;
				var rapportRebond = Math.sin(PIsur2 * (rapport - 1)) + 1;
				return 1 - (Math.cos((2 * nombreRebonds - 1) * Math.PI * rapportRebond) / 2 + 0.5) * hauteurRebond;
			
			case Fondu.types.fluideDepart:
				return 1 - Math.cos(PIsur2 * rapport);
			
			case Fondu.types.fluideDepartArrivee:
				return 1 - (Math.cos(Math.PI * rapport) / 2 + 0.5);
				
			case Fondu.types.continu:
			default:
				return rapport;
		}
	}
	
	/*
	*	this.getIteration()
	*	retourne le coefficient correspondant a l'iteration en cours fonction du type de fondu
	*/
	this.getRapportIterationEnCours = function()
	{
		return this.getRapportIteration(this.i);
	}
	
	/*
	*	this.getValeurIterationEnCours()
	*	retourne la valeur intermediaire entre debut en fin selon le coefficient de l'iteration en cours
	*	
	*	- debut : valeur initiale
	*	- fin : valeur finale
	*	- rapport : coefficient
	*/
	this.getValeurIterationEnCours = function(debut, fin, rapport)
	{
		if (rapport == null)
			rapport = this.getRapportIterationEnCours();
		return debut + (fin - debut) * rapport;
	}
	
	/*
	*	this.start()
	*	demarre le fondu
	*/
	this.start = function()
	{
		if (this.parametres.delai)
		{
			var thisObject = this;
			this.timer = setTimeout(function() { thisObject.iteration(); }, this.parametres.delai);	
			this.parametres.delai = 0;
		}
		else
			this.iteration();
	}
	
	/*
	*	this.stop()
	*	arrete le fondu
	*/
	this.stop = function()
	{
		clearTimeout(this.timer);
		this.timer = null;
	}
	
	/*
	*	this.debutIteration()
	*	fonction a executer en premier dans la fonction iteration()
	*/
	this.debutIteration = function()
	{
		if (this.i == 1 && typeof(this.parametres.onStart) == "function")
			this.parametres.onStart();
		if (typeof(this.parametres.onDebutIteration) == "function")
			this.parametres.onDebutIteration();
	}
	
	/*
	*	this.finIteration()
	*	fonction a executer en dernier dans la fonction iteration()
	*/
	this.finIteration = function()
	{
		if (typeof(this.parametres.onFinIteration) == "function")
			this.parametres.onFinIteration();
		if (++this.i > this.parametres.nbIterations)
		{
			this.timer = null;
			if (typeof(this.parametres.onFinish) == "function")
				this.parametres.onFinish();
		}
		else
		{
			var thisObject = this;
			this.timer = setTimeout(function() { thisObject.iteration(); }, this.parametres.intervalle);
		}
	}
	
	/*
	*	this.iteration()
	*	fonction d'execution de chaque iteration
	*	this.executerIteration() doit etre definie dans la classe fille
	*/
	this.iteration = function()
	{
		this.debutIteration();
		this.executerIteration();
		this.finIteration();
	}
	
	/*
	*	this.executerIteration()
	*	fonction executant une iteration
	*/
	this.executerIteration = function() { }
}
Fondu.types = {
	continu: 0,
	fluideDepart: 1,
	fluideDepartArrivee: 2,
	rebondsArrivee: 3
};
