package animation 
{	
	
	import flash.display.MovieClip
	import flash.events.Event
	import flash.utils.Dictionary
	import manager.Manager;

	public class Animation extends Manager {
		
		public static const EVENT_END_STATE:String = "EVENT_END_STATE"
		
		private static const STATE_PAUSE:String = "STATE_PAUSE"
		private static const STATE_PLAY:String = "STATE_PLAY"
		private static const STATE_STOP:String = "STATE_STOP"
		
		private var pMC:MovieClip		
		private var pStateDictionary:Dictionary
		private var pCurrentStateName:String
		private var pState:String
		private var pTime:Number
		private var pSpeedFactor:Number
		private var pAnimFinishCallback:Function;
		
		public function Animation(aMC:MovieClip) {
			
			pMC = aMC
			
			pStateDictionary = new Dictionary()
			
			pState = STATE_PLAY
			
			pTime = 0.0
			
			pSpeedFactor = 1.0
		}
		
		
		public function mCreateState(aStateName:String, aIsInLoop:Boolean, aSpeedFactor:Number = 1):void {			
			var found:Boolean = false
			var i:int = 1
			while (!found && i <= pMC.totalFrames) {						
				pMC.gotoAndStop(i)
				if (pMC.currentLabel == aStateName) {
					found = true		
				}				
				i++
			}
			if (!found) {
				throw new Error("The state " + aStateName + " doesn't exist in the Flash animation!")
			}
			pStateDictionary[aStateName] = new DataAnimationState(aStateName, aIsInLoop, aSpeedFactor)
		}
		
		
		public function mSetState(aStateName:String, aAnimCallback:Function=null):void {		
			if (pStateDictionary[aStateName] == null) {
 				throw new Error("Trying to set state " + aStateName + " which wasn't created with mCreateState()! " + 
 				" Is this spelled correctly? '" + aStateName + "'")
			}
			
			pCurrentStateName = aStateName
			pMC.gotoAndStop(pCurrentStateName)					
			
			pState = STATE_PLAY
			
			var state:DataAnimationState = pStateDictionary[aStateName]
			mSetSpeedFactor(state.pSpeedFactor)
			
			pAnimFinishCallback = aAnimCallback;
		}
		
		
		override public function mPause():void {
			super.mPause()
			pState = STATE_PAUSE
			pMC.stop()
		}
		
		
		override public function mResume():void {
			super.mResume()
			pState = STATE_PLAY
			pMC.play()
		}
		
		
		override protected function mUpdate(aTime:Number):void {				
			if (pState == STATE_PLAY) {
				
				pTime += aTime * pSpeedFactor
				
				var ended:Boolean
								
				if (pTime > 1 / 30) {					
					pTime = 0
					var newFrame:int = pMC.currentFrame + 1										
					if (newFrame >= pMC.totalFrames) {						
						ended = true
					} else {						
						pMC.gotoAndStop(newFrame)						
					}
				}	
				
				var vCurrentState:DataAnimationState = pStateDictionary[pCurrentStateName]				
				
				if (vCurrentState != null) {			
					//TODO: BUG tengo que agregarle un label extra para que no me reproduzca el cuadro
					//de la siguiente anim.
					if (pMC.currentLabel != pCurrentStateName || ended) { //Si terminó este estado
						if (vCurrentState.pIsInLoop) {
							//Si está en loop, volver al principio														
							pMC.gotoAndStop(pCurrentStateName)							
						} else {
							//Si no, detener la animación
							pMC.stop()
							pState = STATE_STOP
						}
						if (pAnimFinishCallback != null) {
							pAnimFinishCallback(this);
						}
					}
				}
				
			}
			super.mUpdate(aTime)
		}
		
		
		public function mGetMC():MovieClip {
			return pMC
		}
		
		
		public function mGetState():String {
			if (pCurrentStateName == null) {
				throw new Error("No state was set with mSetState()");
			}
			return pCurrentStateName
		}
		
		
		public function mIsStopped():Boolean {
			return pState == STATE_STOP
		}
		
		
		public function mSetSpeedFactor(aSpeedFactor:Number):void {
			pSpeedFactor = aSpeedFactor
		}

		
		public function mGetStateNameComponent(number:Number):String {
			return mGetState().split("_")[number]
		}
		
		
		public function setMC(mc:MovieClip):void
		{
			pMC = mc;
		}
		
	}

}