var Animation = function(name,in_duration, out_duration, fps, wait_time_in_ms_before_progress, pause_after_out_duration_started)
{
	this.name 					= name;
	this.Error 					= false;
	this.items 					= new Array();
	this.in_transitions 		= new Array();
	this.out_transitions 		= new Array();
	this.intermediate_transitions = new Array();
	this.intermediate_durations = new Array();

	this.active_item 			= -1;
	
	this.intermediate_items 	= new Array();
	this.intermediate_start_times = new Array();

	this.fade_out_start_time 	= 0;
	this.fade_start_time 		= 0;
	this.fade_in_duration 		= in_duration;
	this.fade_out_duration 		= out_duration;
	this.pause_after_out_duration_started 		= pause_after_out_duration_started;
	this.wait_time_in_ms_before_progress 		= wait_time_in_ms_before_progress;

	this.time_between_frames = 1000/fps;
	
	this.keep_items_if_possible = false;
}

Animation.prototype =
{
	add_item:
		function( value ) {
			this.items[this.items.length] = value;
		},
	add_in_transition:
		function (value) {
			this.in_transitions[this.in_transitions.length] = value;
		},
	add_out_transition:
		function (value) {
			this.out_transitions[this.out_transitions.length] = value;
		},
	add_intermediate_transition:
		function (step, value, duration) {
			if (!(Array.prototype.isPrototypeOf(this.intermediate_transitions[step])))
			{
				this.intermediate_transitions[step] = new Array();
			}
			this.intermediate_transitions[step][this.intermediate_transitions[step].length] = value;
			this.intermediate_durations[step] = duration;
		},
	enable_keep_items_if_possible :
		function ()
		{
			this.keep_items_if_possible = true;
		},
	start:
		function ()
		{
			if (this.items.length > 0) this.next_item();
		},
	next_item:
		function (  ) {
			
			var out_item = -1;
			var last_intermediate_item = this.intermediate_items[this.intermediate_transitions.length-1] ;
			if (this.intermediate_transitions.length > 0 && this.active_item != -1)
			{
				if (this.intermediate_items.length > 0 && this.intermediate_items.length == this.intermediate_transitions.length) 
				{
					out_item = this.intermediate_items[this.intermediate_items.length-1];
				}
				for (i = 1; i < this.intermediate_transitions.length; i++)
				{
					this.intermediate_items[i] = this.intermediate_items[i-1];
					if(this.intermediate_items[i] != -1)
					{
						this.fade(this.intermediate_items[i] ,"step",i);
					}
					this.intermediate_start_times[i] = new Date().getTime(); 
				}
				this.intermediate_items[0] = this.items[this.active_item];
				this.intermediate_start_times[0] = new Date().getTime(); 
				if ((out_item == -1 && this.keep_items()) || !this.keep_items()) this.fade(this.intermediate_items[0] ,"step",0);

			}
			else
			{
				out_item = this.items[this.active_item];
			}
			
			if (this.keep_items()) out_item = -1;
			
			if (out_item != -1 && out_item != undefined) 
			{
				this.fade_out_start_time = new Date().getTime(); 
				this.fade(out_item,"out");
			}
			if (this.active_item == this.items.length-1 && !this.keep_items())
			{
				this.active_item = 0;
			}
			else 
			{
				this.active_item++;
			}
			
			if ( this.active_item < this.items.length)
			{
//				this.fade(this.items[this.active_item],"in");
				setTimeout(this.name+".fade_start_time = new Date().getTime();"+ this.name+".fade("+this.name+".items["+this.active_item+"],'in');"+this.name+".items["+this.name+".active_item].style.display = 'block'",this.pause_after_out_duration_started);
			}
			
		},
		
	keep_items:
		function ( )
		{
			if (this.keep_items_if_possible)
			{
				return (this.intermediate_transitions.length + 1 >= this.items.length);
			}
			else
			{
				return false;
			}
		},
	fade:
		function ( item_to_animate, direction )
		{
			var step = null;
			if (arguments.length > 2)
			{
				step = arguments[2];
			}
		
			if (direction == "in") 
			{
				percentage_complete = (new Date().getTime()-this.fade_start_time)/this.fade_in_duration;
//				item_to_animate.style.display = "block";
			}
			else if (direction == "out")
			{
				percentage_complete = (new Date().getTime()-this.fade_out_start_time)/this.fade_out_duration;
			}
			else if (direction == "step")
			{
				percentage_complete = (new Date().getTime()-this.intermediate_start_times[step])/this.intermediate_durations[step];
			}
			if (percentage_complete >= 1) 
			{
				if (direction == "in") setTimeout(this.name+".next_item()",this.wait_time_in_ms_before_progress);
				percentage_complete = 1;
			}
			else
			{
			setTimeout(this.name+".fade(document.getElementById('"+item_to_animate.id+"'),'"+direction+"'"+(step != null?","+step:"")+");",this.time_between_frames);
			}
			
			var transitions = new Array();
			
			if (direction == "in") transitions = this.in_transitions;
			else if (direction == "out") transitions = this.out_transitions;
			else if (direction == "step") transitions = this.intermediate_transitions[step];
			
			for ( i = 0; i < transitions.length; i++ ) {
				transitions[i].update( item_to_animate, percentage_complete );
			}
			if (percentage_complete == 1 && direction == "out")
			{
				item_to_animate.style.display = "none";
				for ( i = 0; i < this.in_transitions.length; i++ ) {
					this.in_transitions[i].reset_to_initial_value( item_to_animate );
				}
				for ( i = 0; i <  this.out_transitions.length; i++ ) {
					 this.out_transitions[i].reset_to_initial_value( item_to_animate );
				}
				if (this.intermediate_transitions.length > 0)
				{
				for ( i = 0;  i  < this.intermediate_transitions.length; i++)
				for ( ii = 0; ii < this.intermediate_transitions[i].length; ii++ ) {
					 this.intermediate_transitions[i][ii].reset_to_initial_value( item_to_animate );
				}
			}
		}
	}
}

var OpacityTransition = function(start_value, end_value)
{
	this.start_value = start_value;
	this.end_value = end_value;
	this.original_opacity 		= null;
  	this.original_filter  		= null;
    this.original_MozOpacity 	= null;
    this.original_KhtmlOpacity 	= null;

}

OpacityTransition.prototype.update = function( element, percentage_complete ) {
  
  var opacityAsInt = this.start_value+(this.end_value-this.start_value)*Math.pow(percentage_complete,1.6);
	var opacityAsDecimal = opacityAsInt;
	  
  if (opacityAsInt > 100)
      opacityAsInt = opacityAsDecimal = 100; 
  else if (opacityAsInt < 0)
      opacityAsInt = opacityAsDecimal = 0; 
  
  opacityAsDecimal /= 100;
  if (opacityAsInt < 1)
      opacityAsInt = 1; // IE7 bug, text smoothing cuts out if 0
  

  element.style.opacity = (opacityAsDecimal);
//  element.style.filter  = "alpha(opacity=" + opacityAsInt + ")";
  element.style.MozOpacity = (opacityAsDecimal);
  element.style.KhtmlOpacity = (opacityAsDecimal);

}
	
OpacityTransition.prototype.read_initial_value = function( element ) {
  this.original_opacity = element.style.opacity;
  this.original_filter = element.style.filter;
  this.original_MozOpacity = element.style.MozOpacity;
  this.original_KhtmlOpacity = element.style.KhtmlOpacity;
}

OpacityTransition.prototype.reset_to_initial_value = function( element ) {
  element.style.opacity = this.original_opacity;
//  element.style.filter  = this.original_filter;
  element.style.MozOpacity = this.original_MozOpacity;
  element.style.KhtmlOpacity = this.original_MozOpacity;
}


var PaddingTransition = function (start_value, end_value)
{
	this.start_value = start_value;
	this.end_value = end_value;
	this.original_position = null;
}

PaddingTransition.prototype.update = function( element, percentage_complete ) {
	var paddingValue = (this.start_value+(this.end_value-this.start_value)*Math.pow(percentage_complete,.3))+'px';
	element.style.paddingLeft = paddingValue;
}


PaddingTransition.prototype.read_initial_value = function( element ) {
	this.original_position = element.style.paddingLeft;
}

PaddingTransition.prototype.reset_to_initial_value = function( element ) {
	element.style.paddingLeft = this.original_position;
}

var WidthTransition = function (start_value, end_value)
{
	this.start_value = start_value;
	this.end_value = end_value;
	this.original_position = null;
}

WidthTransition.prototype.update = function( element, percentage_complete ) {
	element.style.width = Math.round(this.start_value+(this.end_value-this.start_value)*Math.pow(percentage_complete,.3))+'px';
}

WidthTransition.prototype.read_initial_value = function( element ) {
	this.original_position = element.style.width;
}

WidthTransition.prototype.reset_to_initial_value = function( element ) {
	element.style.width = this.original_position;
}

var TopTransition = function (start_value, end_value)
{
	this.start_value = start_value;
	this.end_value = end_value;
	this.original_position = null;
}

TopTransition.prototype.update = function( element, percentage_complete ) {
	var topValue = (this.start_value+(this.end_value-this.start_value)*percentage_complete)+'px';
	element.style.top = topValue;
}

TopTransition.prototype.read_initial_value = function( element ) {
	this.original_position = element.style.top;
}

TopTransition.prototype.reset_to_initial_value = function( element ) {
	element.style.top = this.original_position;
}


