/*---------------------------------------------------------------------------------------------------
 * File:		animation.js
 * Author:		Peter Quinn
 * Copyright:	(C)Copyright 2007.  All rights reserved.
 * Version:		1.00
 * Date:					
 *
 * Description:		
 *
 * Methods:			
 *
 *-------------------------------------------------------------------------------------------------*/

var	LEFT				= 0,
	RIGHT				= 1,
	UP					= 2,
	DOWN				= 3,
	ALPHA				= 4,
	WIDTH				= 5,
	HEIGHT				= 6,
	WIDTH_LEFT			= 7,
	HEIGHT_UP			= 8,
	SCROLL_LEFT			= 9,
	SCROLL_RIGHT		= 10,
	SCROLL_UP			= 11,
	SCROLL_DOWN			= 12,
	WIDTH_CENTER		= 13,
	HEIGHT_CENTER		= 14,
	HEIGHT_CENTER_CLOSE	= 15,
	SLIDE_LEFT			= 16,
	SLIDE_RIGHT			= 17;
	

/*---------------------------------------------------------------------------------------------------
 *
 * Animation Class
 *
 */
function Animation( name, object )
{
	this.name			= name || "unnamed";
	this.parent			= parent || null;
	this.object			= object || null;
	this.timer			= null;
	this.waitingTimer	= null;
	this.delay			= 6;
	this.duration		= null;
	this.destination	= 0;
	this.init			= 0;
	this.distance		= 0;
	this.time			= 0;
	this.formula		= null;
	this.action			= null;
	this.step			= 0;
	this.startTime		= 0;
	this.startPos		= 0;
	this.onstart		= null;
	this.onfinish		= null;
	this.onexecute		= null;
	this.active			= false;
	this.paused			= false;
	this.pos			= 0;


	/**
	 * starts the animation
	 */
	this.start = function()
	{
		clearTimeout( this.timer );

		if ( this.onstart )
			this.onstart( this );
			
		this.time		= 0;
		this.init		= this.getStart();
		this.distance	= this.destination - this.init;
		this.step		= this.distance / this.duration / this.duration;
		this.startTime	= new Date().getTime();
		this.active		= true;

		this.exec();
	}
	
	/**
	 * Calculates the initial parameters
	 *
	 * @return int
	 */
	this.getStart = function()
	{
		if ( this.action == HEIGHT_UP || this.action == HEIGHT_CENTER || this.action == HEIGHT_CENTER_CLOSE )
			this.startPos = this.object.getY();
	
		else if ( this.action == WIDTH_LEFT || this.action == WIDTH_CENTER || this.action == HEIGHT_CENTER_CLOSE )
			this.startPos = this.object.getX();
			
		switch( this.action )
		{
			case SCROLL_UP:
			case SCROLL_DOWN:
				return this.object.getScrollY();
				
			case SCROLL_LEFT:
			case SCROLL_RIGHT:
				return this.object.getScrollX();
				
			case UP:
			case DOWN:
				return this.object.getY();
				
			case LEFT:
			case RIGHT:
				return this.object.getX();
			
			case SLIDE_LEFT:
			case SLIDE_RIGHT:
				return this.pos;
				
			case WIDTH:
			case WIDTH_LEFT:
				return this.object.getWidth();
				
			case HEIGHT:
			case HEIGHT_UP:
				return ie ? this.object.getHeight() : this.object.getHeight() - 2;
				
			case WIDTH_CENTER:
				return this.object.getWidth();
				
			case HEIGHT_CENTER:
				return this.object.getHeight();
				
			case HEIGHT_CENTER_CLOSE:
				return ie ? this.object.getHeight() : this.object.getHeight() - 2;
				
			case ALPHA:
				return this.object.getAlpha();
		}
	}
	
	/**
	 * Main animation execution
	 */
	this.exec = function()
	{
		clearTimeout( this.timer );

		this.time = new Date().getTime() - this.startTime;

		if ( ! this.duration || this.time < this.duration )
		{
			if ( ! this.paused )
			{
				switch( this.action )
				{
					case UP:
						this.object.moveY( this.formula() );
						break;
						
					case DOWN:
						this.object.moveY( this.formula() );
						break;
					
					case SLIDE_LEFT:
						this.object.moveX( this.pos-- );
						break;
					
					case SLIDE_RIGHT:
						this.object.moveX( this.pos++ );
						break;
					
					case LEFT:
						this.object.moveX( this.formula( this.object.getX() ) );
						break;
						
					case RIGHT:
						this.object.moveX( this.formula( this.object.getX() ) );
						break;
						
					case WIDTH:
						this.object.resizeX( this.formula() );
						break;
						
					case SCROLL_LEFT:
					case SCROLL_RIGHT:
						this.object.scrollX( this.formula( this.object.getScrollX() ) );
						break;
						
					case SCROLL_UP:
					case SCROLL_DOWN:
						this.object.scrollY( this.formula( this.object.getScrollY() ) );
						break;
						
					case WIDTH_LEFT:
						n = this.formula();
						this.object.resizeX( n );
						this.object.moveX( this.init + this.startPos - n );
						break;
						
					case HEIGHT:
						this.object.resizeY( this.formula() );
						break;
						
					case HEIGHT_UP:
						n = this.formula();
						this.object.resizeY( n );
						this.object.moveY( this.init + this.startPos - n );
						break;
						
					case WIDTH_CENTER:
						n = this.formula();
						this.object.resizeX( n );
						this.object.moveX( this.init + this.startPos - (n / 2) );
						break;
						
					case HEIGHT_CENTER:
						n = this.formula();
						this.object.resizeY( n );
						this.object.moveY( this.init + this.startPos - (n / 2) );
						break;
						
					case HEIGHT_CENTER_CLOSE:
						n = this.formula();
						this.object.resizeY( n );
						this.object.moveY( this.init - this.startPos - (n / 2) );
						break;
						
					case ALPHA:
						this.object.alpha( this.formula() );
						break;
				}
				
				if ( this.onexecute )
					this.onexecute( this );
			}
			
			this.timer = setTimeout( this.name + ".exec()", this.delay );
		}
		else
		{
			this.active = false;
			
			switch( this.action )
			{
				case UP:
					this.object.moveY( this.destination );
					break;
					
				case DOWN:
					this.object.moveY( this.destination );
					break;
					
				case LEFT:
					this.object.moveX( this.destination );
					break;
					
				case RIGHT:
					this.object.moveX( this.destination );
					break;
					
				case WIDTH:
					this.object.resizeX( this.destination );
					break;
					
				case WIDTH_LEFT:
					this.object.resizeX( this.destination );
					this.object.moveX( this.init + this.startPos - this.destination );
					break;
					
				case HEIGHT:
					this.object.resizeY( this.destination );
					break;
					
				case HEIGHT_UP:
					this.object.resizeY( this.destination );
					this.object.moveY( this.init + this.startPos - this.destination );
					break;
				
				case WIDTH_CENTER:
					this.object.resizeX( this.destination );
					this.object.moveX( this.init + this.startPos - (this.destination / 2) );
					break;
						
				case HEIGHT_CENTER:
					this.object.resizeY( this.destination );
					this.object.moveY( this.init + this.startPos - (this.destination / 2) );
					break;
					
				/*
				case HEIGHT_CENTER_CLOSE:
					this.object.resizeY( this.destination );
					this.object.moveY( this.init + this.startPos - (this.destination / 2) );
					break;
				*/
				
				case ALPHA:
					this.object.alpha( this.destination );
					break;
			}

			if ( this.onfinish )
				this.onfinish( this );
				
			if ( this.onfinal )
				this.onfinal( this );
		}
	}
	
	this.stop = function()
	{
		clearTimeout( this.timer );
	}
	
	this.pause = function( flag )
	{
		this.paused = flag;
	}
	
	this.incremental = function( n )
	{
		switch( this.action )
		{
			case UP:
			case LEFT:
			case SCROLL_LEFT:
			case SLIDE_LEFT:
				return n;
				
			case DOWN:
			case RIGHT:
			case SCROLL_RIGHT:
			case SLIDE_RIGHT:
				return ++n;
		}
	}
	
	/**
	 * Power function
	 */
	this.pow = function()
	{
		return this.distance - Math.round( Math.pow( this.duration - this.time, 2 ) * this.step ) + this.init;
	}
	
	/**
	 * Power function
	 */
	this.pow2 = function( p, x )
	{
		this.object.layer.innerHTML += "a ";
		return Math.pow( p, x || 6 );
	}
	
	/**
	 * EXPO function
	 */
	this.expo = function( p )
	{
		this.object.layer.innerHTML += " e";
		return Math.pow( 2, 8 * (p - 1) );
	}
	
	/**
	 * Circular function
	 */
	this.circ = function( p )
	{
		return 1 - Math.sin( Math.acos( p ) );
	}
	
	/**
	 * Sine function
	 */
	this.sine = function( p )
	{
		return 1 - Math.sin( (1 - p) * Math.PI / 2 );
	}
	
	/**
	 * Back function
	 */
	this.back = function( p, x )
	{
		x = x[0] || 1.618;
		return Math.pow( p, 2 ) * ( (x + 1) * p - x );
	}
	
	/**
	 * Bounce function
	 */
	this.bounce = function( p )
	{
		var	value;
		
		for( var a = 0, b = 1; 1; a += b, b /= 2 )
			if ( p >= (7 - 4 * a) / 11 )
			{
				value = -Math.pow( (11 - 6 * a - 11 * p) / 4, 2 ) + b * b;
				break;
			}
			
		return value;
	}
	
	/**
	 * Elastic function
	 */
	this.elastic = function( p, x )
	{
		return Math.pow( 2, 10 * --p ) * Math.cos( 20 * p * Math.PI * (x[0] || 1) / 3 );
	}


	// sets the default animation function
	this.formula = this.pow;
}


/*-------------------------------------------------------------------------------------------------*/
