function PIAColor(fromColor, toColor)
{
	this.from = this._getColorFrom(fromColor);
	this.to = this._getColorFrom(toColor);
}
PIAColor.prototype._getValue = function(ofValue)
{
	var getValue = function (from, to, value)
	{
		return(parseInt(from + (to - from) * value));
	}
	
	valeur = {
		red: getValue(this.from.red, this.to.red, ofValue),
		green: getValue(this.from.green, this.to.green, ofValue),
		blue: getValue(this.from.blue, this.to.blue, ofValue),
		alpha: getValue(this.from.alpha, this.to.alpha, ofValue)
	};
	
	if(valeur.alpha != 1)
	{
		return('rgba('+valeur.red+','+valeur.green+','+valeur.blue+','+valeur.alpha+')');
	}
	else
	{
		return('rgb('+valeur.red+','+valeur.green+','+valeur.blue+')');
	}
};
PIAColor.prototype._HSL2RGB = function(hue, saturation, lightness, alphaValue)
{
	var hueMax = 360; satMax = 1; ligMax = 1; RGBMax = 255;
	var H0 = (6*hue)/hueMax;
	if(lightness<=(ligMax/2))
	{
		GM = RGBMax * (lightness/ligMax)*(1+saturation/satMax);
		pm = RGBMax * (lightness/ligMax)*(1-saturation/satMax);
	}
	else
	{
		GM = RGBMax * ((lightness/ligMax)*(1-saturation/satMax) + (saturation/satMax));
		pm = RGBMax * ((lightness/ligMax)*(1+saturation/satMax) - (saturation/satMax));
	}
	delta = GM - pm;
	
	switch(parseInt(H0))
	{
		case 0:
			return({blue:pm,  green:pm+H0*delta,     red:GM,   alpha: alphaValue});
		case 1:
			return({blue:pm,  red:pm+(2-H0)*delta,   green:GM, alpha: alphaValue});
		case 2:
			return({red:pm,   blue:pm+(H0-2)*delta,  green:GM, alpha: alphaValue});
		case 3:
			return({red:pm,   green:pm+(4-H0)*delta, blue:GM,  alpha: alphaValue});
		case 4:
			return({green:pm, red:pm+(H0-4)*delta,   blue:GM,  alpha: alphaValue});
		case 5:
			return({green:pm, blue:pm+(6-H0)*delta,  red:GM,   alpha: alphaValue});
	}
}
PIAColor.prototype._getColorFrom = function(varToRead)
{
	if(typeof(varToRead.alpha) == 'undefined' && typeof(varToRead.a) == 'undefined')
	{
		var alphaValue = 1;
	}
	else if(typeof(varToRead.alpha) != 'undefined')
	{
		var alphaValue = varToRead.alpha;
	}
	else if(typeof(varToRead.a) != 'undefined')
	{
		var alphaValue = varToRead.a;
	}

	if(typeof(varToRead.gray) != 'undefined')//Gris
	{
		return({red:varToRead.gray, blue:varToRead.gray, green: varToRead.gray, alpha: alphaValue});
	}

	else if(typeof(varToRead.hue) != 'undefined' && typeof(varToRead.saturation) != 'undefined' && typeof(varToRead.lightness) != 'undefined')//HSL (long)
	{
		return(this._HSL2RGB(varToRead.hue, varToRead.saturation, varToRead.lightness, alphaValue));
	}
	else if(typeof(varToRead.h) != 'undefined' && typeof(varToRead.s) != 'undefined' && typeof(varToRead.l) != 'undefined')//HSL (court)
	{
		return(this._HSL2RGB(varToRead.h, varToRead.s, varToRead.l, alphaValue));
	}

	else if(typeof(varToRead.r) != 'undefined' && typeof(varToRead.g) != 'undefined' && typeof(varToRead.b) != 'undefined')//RGB (court)
	{
		return({red:varToRead.r, green:varToRead.g, blue:varToRead.b, alpha: alphaValue});
	}
	else//RGB (long)
	{
		return({red:varToRead.red, green:varToRead.green, blue:varToRead.blue, alpha: alphaValue});
	}
}

function PIASize(fromSize, toSize, withUnit)
{
	this.from = parseFloat(fromSize);
	this.to = parseFloat(toSize);
	this.unit = withUnit;
}
PIASize.prototype._getValue = function(ofValue)
{
	return(this.from + (this.to - this.from) * ofValue + this.unit);
};

function PIANumeric(fromNum, toNum)
{
	this.from = fromNum;
	this.to = toNum;
}
PIANumeric.prototype._getValue = function(ofValue)
{
	return(this.from + (this.to - this.from) * ofValue);
};

function PIA(cssName, propriete, duration, fps, endFunc)
{
	this.cssName = cssName;
	this.effect = propriete;
	this.duration = duration;
	this.propriete = null;
	this.fps = fps;
	this._animationValue = 0;
	this._timer = null;
	this._parent = null;
	if(typeof(endFunc) == 'function')
		{ this.endFunc = endFunc; }
	else
		{ this.endFunc = null; }
	this.eventProgress = function (state) {};
}
PIA.prototype.start = function()
{
	this._animationValue = 0;
	if(this._timer != null) { return(0); }
	this._timer = window.setInterval(function(obj){ obj._nextStep(); }, Math.ceil(1000/this.fps), this);
};
PIA.prototype.stop = function()
{
	if(this._timer == null) { return(0); }
	window.clearInterval(this._timer);
	this._timer = null;
}
PIA.prototype._nextStep = function()
{
	this._animationValue += 1/(this.duration*this.fps);
	if(this._animationValue > 1) { this._animationValue = 1; }
	
	var valeur = this.effect._getValue(this._animationValue);
	this._parent.HTML.style.setProperty(this.cssName, valeur, '');

	this.eventProgress(this._animationValue);
	this._parent._elementProgress();

	if(this._animationValue == 1)
	{
		this.stop();
		if(this.endFunc != null) { this.endFunc(); }
		this._parent._elementEnd();
	}
};

function PIAElement(HTML)
{
	this.HTML = HTML;
	this._elements = new Array();
	this.event = {
		progress : function(progress) {},
		ended : function() {}
	};
	
}
PIAElement.prototype.add = function(PIA) {
	PIA._parent = this;
	this._elements.push(PIA);
};
PIAElement.prototype.remove = function(id) {
	this._elements[id].stop();
	this._elements.splice(id,1);
};
PIAElement.prototype.start = function() {
	if(this._elements.length > 0)
	{
		for(var tour=0;tour<this._elements.length;tour++)
			{ this._elements[tour].start(); }
	}
};
PIAElement.prototype.stop = function() {
	if(this._elements.length > 0)
	{
		for(var tour in this._elements)
			{ this._elements[tour].stop(); }
	}
}
PIAElement.prototype._elementEnd = function() {
	var endCount = 0;
	for(var tour in this._elements)
	{
		if(this._elements[tour]._animationValue == 1)
			{ endCount++; }
	}

	if(endCount == this._elements.length)
	{
		this._elements = new Array();
		this.event.ended();
	}
};
PIAElement.prototype._elementProgress = function() {
	if(this._elements.length > 0)
	{
		var progression = 0;
		for(var tour in this._elements)
		{
			progression += this._elements[tour]._animationValue;
		}
	}

	this.event.progress(progression/this._elements.length);
};
PIAElement.prototype.getProgress = function() {
	if(this._elements.length > 0)
	{
		var progression = 0;
		for(var tour in this._elements)
		{
			progression += this._elements[tour]._animationValue;
		}
	}

	return(progression/this._elements.length);
}
