package com.guru.display.graphicDigit
{
	import com.guru.call.FunctionCall;
	import com.guru.call.ICall;
	import flash.display.MovieClip;
	/**
	 * ...
	 * @author Eddy Lee
	 */
	public class GraphicDigitGroup
	{
		//000 -> 123
		public static var JUMP_MODE:String = "jump";
		//000 -> 001 -> 002 -> 003 -> ... -> 123
		public static var NORMAL_MODE:String = "normal";
		//000 -> 001 -> 002 -> 003 -> ... -> 123 (without digit animation)
		public static var FAST_MODE:String = "fast";
		//000 -> 111 -> 122 -> 123
		public static var SKIP_MODE:String = "skip";
		//000 -> 123 (with animation)
		public static var ADVANCED_JUMP_MODE:String = "advanced_jump";
		
		private var mTimeline_mc:MovieClip;
		private var mDigit_array:Array;
		private var mStartValue_num:Number;
		private var mCurrentValue_num:Number;
		private var mTargetValue_num:Number;
		
		public function GraphicDigitGroup(pTimeline_mc:MovieClip) 
		{
			mTimeline_mc = pTimeline_mc;
			
			mCurrentValue_num = 0;
			mTargetValue_num = 0;
			
			mDigit_array = new Array();
			var digit_mc:MovieClip;
			for (var i:Number = 0; digit_mc = mTimeline_mc["digit" + i + "_mc"]; i++ )
			{
				var digit:GraphicDigit = new GraphicDigit(digit_mc, i);
				mDigit_array.push(digit);
			}
		}
		
		public function dispose():void
		{
			while (mDigit_array.length > 0)
			{
				var digit:GraphicDigit = mDigit_array.shift();
				digit.dispose();
			}
		}
		
		/**
		 * For non negative value only
		 */
		public function setNumber(pValue_num:Number, pDoneCall:ICall = null, pAnimationMode_str:String = "normal"):void
		{
			mStartValue_num = mCurrentValue_num;
			pValue_num = Math.max(0, pValue_num);
			
			for (var i:Number = 0; i < mDigit_array.length; i++ )
			{
				GraphicDigit(mDigit_array[i]).stop();
			}
			
			this.doSetNumber(pValue_num, pDoneCall, pAnimationMode_str);
		}
		
		public function doSetNumber(pValue_num:Number, pDoneCall:ICall = null, pAnimationMode_str:String = "normal"):void
		{
			mTargetValue_num = pValue_num;
			
			if (mTargetValue_num == mCurrentValue_num)
			{
				if(pDoneCall != null)
					pDoneCall.execute();
				return;
			}
			
			if (pAnimationMode_str == JUMP_MODE)
			{
				mCurrentValue_num = mTargetValue_num;
			}
			else if (pAnimationMode_str == NORMAL_MODE)
			{
				if (mTargetValue_num > mCurrentValue_num)
					mCurrentValue_num++;
				else if (mTargetValue_num < mCurrentValue_num)
					mCurrentValue_num--;
			}
			else if (pAnimationMode_str == FAST_MODE)
			{
				if (mTargetValue_num > mCurrentValue_num)
					mCurrentValue_num++;
				else if (mTargetValue_num < mCurrentValue_num)
					mCurrentValue_num--;
			}
			else if (pAnimationMode_str == ADVANCED_JUMP_MODE)
			{
				mCurrentValue_num = mTargetValue_num;
			}
			else if (pAnimationMode_str == SKIP_MODE)
			{
				mCurrentValue_num = this.getNextSkipValue(mCurrentValue_num, mTargetValue_num);
			}
			
			var forward_bol:Boolean = mStartValue_num < mTargetValue_num;
			var value_str:String = this.getNumberInStringFormat(mCurrentValue_num);
			var doneCall:ICall = new FunctionCall(this, doSetNumber, mTargetValue_num, pDoneCall, pAnimationMode_str);
			
			for (var i:Number = 0; i < mDigit_array.length; i++ )
			{
				if (GraphicDigit(mDigit_array[i]).getNumber() != Number(value_str.charAt(i)))
				{
					GraphicDigit(mDigit_array[i]).setNumber(Number(value_str.charAt(i)));
					
					if (pAnimationMode_str == JUMP_MODE)
					{
						GraphicDigit(mDigit_array[i]).refresh(false, doneCall, forward_bol);
					}
					else if (pAnimationMode_str == NORMAL_MODE)
					{
						GraphicDigit(mDigit_array[i]).refresh(true, doneCall, forward_bol);
					}
					else if (pAnimationMode_str == FAST_MODE)
					{
						GraphicDigit(mDigit_array[i]).refresh(false, doneCall, forward_bol);
					}
					else if (pAnimationMode_str == ADVANCED_JUMP_MODE)
					{
						GraphicDigit(mDigit_array[i]).refresh(true, doneCall, forward_bol);
					}
					else if (pAnimationMode_str == SKIP_MODE)
					{
						GraphicDigit(mDigit_array[i]).refresh(true, doneCall, forward_bol);
					}
					doneCall = null;
				}
			}
		}
		
		public function getNumber():Number
		{
			return this.getGraphicDigitValue();
		}
		
		public function addNumber(pDelta_num:Number, pDoneCall:ICall = null, pAnimationMode_str:String = "fast"):void
		{
			this.setNumber(mCurrentValue_num + pDelta_num, pDoneCall, pAnimationMode_str);
		}
		
		public function getGraphicDigitValue():Number
		{
			var value_str:String = "";
			for (var i:Number = 0; i < mDigit_array.length; i++ )
			{
				mDigit_array[i] = value_str + GraphicDigit(mDigit_array[i]).getNumber();
			}
			return Number(value_str);
		}
		
		public function getNumberInStringFormat(pInput_num:Number):String
		{
			var value_str:String = String(pInput_num);
			value_str = this.addZero(value_str, mDigit_array.length);
			return value_str;
		}
		
		private function addZero(pInputValue:*, pNumeberOfDigit_num:Number):String
		{
			pInputValue = String(pInputValue);
			while (pInputValue.length < pNumeberOfDigit_num)
			{
				pInputValue = "0" + pInputValue;
			}
			return pInputValue;
		}
		
		private function getNextSkipValue(pFrom_num:Number, pTo_num:Number):Number
		{
			if (pFrom_num == pTo_num)
				return pTo_num;
			
			var forward_bol:Boolean = pFrom_num < pTo_num;
			var numLength_num:Number = Math.max(pFrom_num.toString().length, pTo_num.toString().length)
			var from_str:String = this.addZero(pFrom_num, numLength_num);
			var to_str:String = this.addZero(pTo_num, numLength_num);
			var next_str:String = "";
			
			for (var i:Number = 0; i < numLength_num; i++ )
			{
				if (from_str.charAt(i) != to_str.charAt(i))
				{
					var temp_str:String;
					if (forward_bol)
						temp_str = String(Number(from_str.charAt(i)) + 1);
					else
						temp_str = String(Number(from_str.charAt(i)) + 9);
					next_str = next_str + temp_str.charAt(temp_str.length-1);
				}
				else
				{
					next_str = next_str + from_str.charAt(i);
				}
				
			}
			
			return Number(next_str);
		}
	}

}