
/*
 *
 * CWAnimationDelegate
 *
 * animationDidEnd( anim )
 * animationDidStop( anim )
 * animationShouldStart( anim ) as boolean
 * animationValueForProgress( anim, progress ) as float
 * animationDidReachProgressMark( anim, progress )
 *
 */
 
var	CWAnimationCurveLinear = function _CWAnimationCurveLinear( t, b, c, d )
								{
									return c;
								} 

var	CWAnimationCurveEaseIn = function _CWAnimationCurveQuadEaseIn( t, b, c, d )
								{
									return c*(t/=d)*t + b;
								} 

var	CWAnimationCurveEaseOut = function _CWAnimationCurveQuadEaseOut( t, b, c, d )
								{
									return -c *(t/=d)*(t-2) + b;
								}

var	CWAnimationCurveEaseInOut = function _CWAnimationCurveQuadEaseInOut( t, b, c, d )
								{
									if ((t/=d/2) < 1) return c/2*t*t + b;
									return -c/2 * ((--t)*(t-2) - 1) + b;
								}


function CWAnimation()
{
	this._timer 				= 0;
	this._curve 				= CWAnimationCurveLinear;
	this._duration 				= 2.0;
	this._delegate 				= undefined;
	this._isAnimating 			= false;
	this._currentProgress 		= 0.0; // 0.0 to 1.0
	this._currentValue			= 0.0; // 0.0 to 1.0 - can be less or more to create rubber band effects
	this._frameRate				= 30.0;
	
	this._totalFrames			= this._frameRate * this._duration;
	this._currentFrame			= 0;
	
	/*
	 * setters and getters
	 *
	 */
	 
	this.animationCurve = function()
	{
		return this._curve;
	}
	
	this.setAnimationCurve = function( newCurve )
	{
		this._curve = newCurve;
	}
	
	this.duration = function()
	{
		return this._duration;
	}
	
	this.setDuration = function( newDuration )
	{
		this._duration = newDuration;
		this._recalculateAnimationInfo();
	}
	
	this.frameRate = function()
	{
		return this._frameRate;
	}
	
	this.setFrameRate = function( newFrameRate )
	{
		this._frameRate = newFrameRate;
		this._recalculateAnimationInfo();
	}
	
	this.delegate = function()
	{
		return this._delegate;
	}
	
	this.setDelegate = function( newDelegate )
	{
		this._delegate = newDelegate;
	}
	
	this.currentProgress = function( newProgress )
	{
		return this._currentProgress;
	}
	
	this.setCurrentProgress = function( newProgress )
	{
		this._currentProgress = newProgress;
		this._sendAnimationValueForProgress();
		this._sendAnimationDidReachProgressMark();
	}
	
	this.currentValue = function()
	{
		return this._currentValue;
	}
	
	this.isAnimating = function()
	{
		return this._isAnimating;
	}
	
	/*
	 *
	 * private functions
	 *
	 */
	
	this._recalculateAnimationInfo = function()
	{
		this._totalFrames			= this._frameRate * this._duration;
	}
	
	this._sendAnimationValueForProgress = function()
	{
		if ( this._delegate && this._delegate.animationValueForProgress )
		{
			this._currentValue = this._delegate.animationValueForProgress( this, this.currentProgress() );
		}
		else
		{
			if ( this._curve )
				this._currentValue = this._curve( this._currentFrame, 0.0, this.currentProgress(), this._totalFrames );
			else
				this._currentValue = this.currentProgress();
		}
	}
	
	this._sendAnimationDidReachProgressMark = function()
	{
		if ( this._delegate && this._delegate.animationDidReachProgressMark )
		{
			this._delegate.animationDidReachProgressMark( this, this.currentProgress() );
		}
	}
	
	this._sendAnimationDidEnd = function()
	{
		if ( this._delegate && this._delegate.animationDidEnd )
		{
			this._delegate.animationDidEnd( this );
		}
	}
	
	this._sendAnimationDidStop = function()
	{
		if ( this._delegate && this._delegate.animationDidStop )
		{
			this._delegate.animationDidStop( this );
		}
	}
	
	this._sendAnimationShoudStart = function()
	{
		if ( this._delegate && this._delegate.animationShouldStart )
		{
			return this._delegate.animationShouldStart( this );
		}
		return true;
	}
	
	this._startAnimation = function(base)
	{
		
	}
	
	/*
	 *
	 * animation
	 *
	 */
	 
	this.startAnimation = function()
	{
		if ( this.isAnimating() ) return;
		if ( this._sendAnimationShoudStart() )
		{
			this._currentProgress = 0;
			this._currentValue = 0;
			this._currentFrame = 0;
			this._recalculateAnimationInfo();
			
			this._isAnimating = true;
			
			if ( this._timer )
				window.clearInterval( this._timer );
			
			this._timer = window.setInterval( 
				function( self )
				{
					if ( self._currentFrame > self._totalFrames ) return;
					
					self.setCurrentProgress( self._currentFrame / self._totalFrames );
					
					if ( self._currentFrame == self._totalFrames )
					{
						window.clearInterval( self._timer );
						self._isAnimating = false;
						self._sendAnimationDidEnd();
						return;	
					}
					
					self._currentFrame++;
				}
				, (this._duration * 1000.0) / this._totalFrames, this );
		}
	}	
	
	this.stopAnimation = function()
	{
		if ( ! this.isAnimating() ) return;
		if ( this._timer )
				window.clearInterval( this._timer );
		this._isAnimating = false;
		this._sendAnimationDidStop();
	} 
}

/*
 *
 * DOMElement Animation
 *
 * delegate
 * domAnimationDidStart( anim )
 * domAnimationDidEnd( anim )
 * domAnimationDidStop( anim )
 *
 */



function CWDOMAnimation()
{
	this._animation = new CWAnimation(); // animation element
	this._animation.DOMAnimation = this;
	this._animation.setAnimationCurve( CWAnimationCurveEaseIn );
	this._animation.setDelegate(this);
	this._element;// element to be animated;
	this._startStyle;;
	this._endStyle;
	this._delegate;
	
	// delegate
	
	this.animationShouldStart = function(anim)
	{
		//window.console.log("animationShouldStart");	
		
		if ( this._delegate && this._delegate.domAnimationDidStart )
			this._delegate.domAnimationDidStart(anim.DOMAnimation);
		
		return true;
	}

	this.animationDidEnd = function(anim)
	{
		//window.console.log("animationDidEnd");
		if ( this._delegate && this._delegate.domAnimationDidEnd )
			this._delegate.domAnimationDidEnd(anim.DOMAnimation);
	}
	
	this.animationDidStop = function(anim)
	{
		//window.console.log("animationDidStop");
		if ( this._delegate && this._delegate.domAnimationDidStop )
			this._delegate.domAnimationDidStop(anim.DOMAnimation);
	}
	
	this.animationDidReachProgressMark = function( anim, progress )
	{
		var	value = anim.currentValue();
		var	domAnim = anim.DOMAnimation;
		
		//window.console.log( "animationDidReachProgressMark" + value );
		
		if ( typeof domAnim._startStyle.Left != "undefined" && typeof domAnim._endStyle.Left != "undefined" )
			domAnim._element.style.left = domAnim._startStyle.Left + ( ( domAnim._endStyle.Left - domAnim._startStyle.Left ) * value );
		
		if ( typeof domAnim._startStyle.Top != "undefined" && typeof domAnim._endStyle.Top != "undefined" )
			domAnim._element.style.Top = domAnim._startStyle.Top + ( ( domAnim._endStyle.Top - domAnim._startStyle.Top ) * value );
			
		if ( typeof domAnim._startStyle.Right != "undefined" && typeof domAnim._endStyle.Right != "undefined" )
			domAnim._element.style.Right = domAnim._startStyle.Right + ( ( domAnim._endStyle.Right - domAnim._startStyle.Right ) * value );
			
		if ( typeof domAnim._startStyle.Bottom != "undefined" && typeof domAnim._endStyle.Bottom != "undefined" )
			domAnim._element.style.Bottom = domAnim._startStyle.Bottom + ( ( domAnim._endStyle.Bottom - domAnim._startStyle.Bottom ) * value );
			
		if ( typeof domAnim._startStyle.Width != "undefined" && typeof domAnim._endStyle.Width != "undefined" )
			domAnim._element.style.Width = domAnim._startStyle.Width + ( ( domAnim._endStyle.Width - domAnim._startStyle.Width ) * value );
			
		if ( typeof domAnim._startStyle.Height != "undefined" && typeof domAnim._endStyle.Height != "undefined" )
			domAnim._element.style.Height = domAnim._startStyle.Height + ( ( domAnim._endStyle.Height - domAnim._startStyle.Height ) * value );
			
		if ( typeof domAnim._startStyle.opacity != "undefined" && typeof domAnim._endStyle.opacity != "undefined" )
			domAnim._element.style.opacity = domAnim._startStyle.opacity + ( ( domAnim._endStyle.opacity - domAnim._startStyle.opacity ) * value );
			
		
	}
	
	// private
	this._getStyleAsObject = function(aStyle)
	{
		// properties that we can use
		// Left, Top, Right, Bottom, Width, Height
		// opacity
		
		var	output = new Object();
		
		if ( aStyle.Left )
		{
			if ( typeof aStyle.Left == "string" )
				output.Left = parseFloat( aStyle.Left );
			else
				output.Left = aStyle.Left;
		}
		
		if ( aStyle.Right )
		{
			if ( typeof aStyle.Right == "string" )
				output.Right = parseFloat( aStyle.Right );
			else
				output.Right = aStyle.Right;
		}
		
		if ( aStyle.Top )
		{
			if ( typeof aStyle.Top == "string" )
				output.Top = parseFloat( aStyle.Top );
			else
				output.Top = aStyle.Top;
		}
		
		if ( aStyle.Bottom )
		{
			if ( typeof aStyle.Bottom == "string" )
				output.Bottom = parseFloat( aStyle.Bottom );
			else
				output.Bottom = aStyle.Bottom;
		}
		
		if ( aStyle.Width )
		{
			if ( typeof aStyle.Width == "string" )
				output.Width = parseFloat( aStyle.Width );
			else
				output.Width = aStyle.Width;
		}
		
		if ( aStyle.Height )
		{
			if ( typeof aStyle.Height == "string" )
				output.Height = parseFloat( aStyle.Height );
			else
				output.Height = aStyle.Height;
		}
		
		if ( aStyle.opacity )
		{
			if ( typeof aStyle.opacity == "string" )
				output.opacity = parseFloat( aStyle.opacity );
			else
				output.opacity = aStyle.opacity;
		}
		
		return output;
	}
	
	// function
	this.setDelegate = function( aDelegate )
	{
		this._delegate = aDelegate;
	}
	
	this.animation = function()
	{
		return this._animation;
	}
	
	this.setElement = function( elem )
	{
		this._element = elem;	
	}
	
	this.element = function()
	{
		return this._element;
	}
	
	this.setEndStyle = function( endStyle )
	{
		this._endStyle = this._getStyleAsObject(endStyle);
	}
	
	this.setStartStyle = function( startStyle )
	{
		this._startStyle = this._getStyleAsObject(startStyle);		
	}
	
	this.startAnimation = function()
	{
		if ( ! this._element ) return;
		if ( ! this._endStyle ) return;
		if ( this._animation.isAnimating() ) return;

		if ( this._startStyle == undefined ) this._startStyle = this._getStyleAsObject(this._element.style);

		this._animation.startAnimation();
	}
	
	this.stopAnimation = function()
	{
		this._animation.stopAnimation();
	}
}











