/// <summary> 
    /// State machine of game animation. which is a sub state of main State machine.
    /// </summary>
    public void UpdateAnimation()
    {
        if (m_IsEnd)
            return;

        //! nomal win case: sound play at stop of spinning.
        if(!GameVariables.Instance.IsThreeScatters() && !GameVariables.Instance.IS_FREEGAME)
            WinAmountAnim.Instance.PlayWinIncSound();

        if (CURRENT_STATE != NEXT_STATE)
        {
        //	Debug.Log ("Animation :  " + CURRENT_STATE + "->" + NEXT_STATE);
            CURRENT_STATE = NEXT_STATE;
        }
        //	Debug.Log ("Animation Current State :  " + CURRENT_STATE );
        //Animation State Machine
        switch (CURRENT_STATE)
        {
            //Notice: all delay will cause update block to run many times... ,it bring some unexpected issue.
        case STATE.AS_IDLE:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                if(GameVariables.Instance.IS_FREEGAME || GameVariables.Instance.IsThreeScatters())
                    WinManager.Instance.END_WIN = WinAmountAnim.Instance.CURRENT_WIN + WinManager.Instance.TOTALWIN;

                m_InnerSate = INNER_STATE.IS_UPDATE;

                break;
            case INNER_STATE.IS_UPDATE:
                TEMP_NEXT = STATE.AS_STAEONE;
                m_InnerSate = INNER_STATE.IS_EXIT;

                break;
            case INNER_STATE.IS_EXIT:
                NEXT_STATE = TEMP_NEXT;
                m_InnerSate = INNER_STATE.IS_ENTER;

                break;

            }
            break;

        case STATE.AS_STAEONE:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:

                m_InnerSate = INNER_STATE.IS_UPDATE;

                break;
            case INNER_STATE.IS_UPDATE:
                if(IconAnim.Instance.IS_START_LINEANI == true)// && GameVariables.Instance.IS_INCRESED == true)
                {
                    m_InnerSate = INNER_STATE.IS_EXIT;
                    TEMP_NEXT = STATE.AS_STATETWO;
                }
                else
                {
                    IconAnim.Instance.BlinkWinIcons();
                    WinAmountAnim.Instance.UpdateWinAmount();

                    if(WinManager.Instance.Is_BigWin() && !IsPlayBigWin)
                    {
                        IsPlayBigWin = true;
                        GoldCoinEmitter.Instance.StartGoldCoinAnimation();
                    }

                }
                break;
            case INNER_STATE.IS_EXIT:
                NEXT_STATE = TEMP_NEXT;
                m_InnerSate = INNER_STATE.IS_ENTER;

                break;

            }
            break;

        case STATE.AS_STATETWO:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                //make scatter animation play frist
                IconAnim.Instance.IsFinshScatter = false;
                m_InnerSate = INNER_STATE.IS_UPDATE;

                break;
            case INNER_STATE.IS_UPDATE:
                AnimManager.Instance.CheckSkipInput();
                //Blinking icon finsh, start to blink line and other animations.

                if (Input.GetKeyDown (KeyCode.E))
                {
                    GameVariables.Instance.EDITOR_FLAG  = GameVariables.EDIT_STATES.NG_IDLE;
                }

                if(IconAnim.Instance.IS_START_LINEANI)
                {
                    LineAnim.Instance.DrawPlayLines();
                    IconAnim.Instance.PlayAnimation();
                    WinAmountAnim.Instance.UpdateWinAmount();
                }
                //skip input detected(main game/ free game) or finish win amount increament(free game), exit animation state.
                if( (GameVariables.Instance.IS_INCRESED && GameVariables.Instance.IS_FREEGAME && !GameVariables.Instance.IsThreeScatters())
                        ||  !IconAnim.Instance.IS_START_LINEANI)
                {
                    TEMP_NEXT = STATE.AS_END;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                break;
            case INNER_STATE.IS_EXIT:

                NEXT_STATE = TEMP_NEXT;

                m_InnerSate = INNER_STATE.IS_ENTER;

                break;

            }
            break;

        case STATE.AS_END:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:

                m_InnerSate = INNER_STATE.IS_UPDATE;

                break;
            case INNER_STATE.IS_UPDATE:

                m_InnerSate = INNER_STATE.IS_EXIT;

                break;
            case INNER_STATE.IS_EXIT:

                m_IsEnd = true;
                if(GameVariables.Instance.IsThreeScatters())
                {
                    GameObject.Find(GameVariables.Instance.BG_NAME).GetComponent<OTSprite>().frameIndex = 1;

                    //! ToDo:  Animation for Game Transition (Main-Free)

                }
                IconAnim.Instance.IS_START_LINEANI = false;

                NEXT_STATE = STATE.AS_IDLE;
                m_InnerSate = INNER_STATE.IS_ENTER;

                break;

            }
            break;

        }// End of Animation State Machine.
    }
 /// <summary> 
 /// Initialize function which pre-excuate before all start functions.
 /// </summary>
 void Awake()
 {
     CURRENT_STATE 	= STATE.GS_IDLE;
     NEXT_STATE 	= STATE.GS_IDLE;
     m_TempNS = STATE.GS_IDLE;
     m_InnerSate = INNER_STATE.IS_ENTER;
     isExecuting = false;
     m_WinShowTime = GameVariables.SHOW_WIN_TIME;
 }
 public void ResetAnimationState()
 {
     IconAnim.Instance.IS_START_LINEANI = false;
     CURRENT_STATE = STATE.AS_IDLE;
     NEXT_STATE = STATE.AS_IDLE;
     m_InnerSate = INNER_STATE.IS_ENTER;
     GameVariables.Instance.IS_INCRESED = true;
 }
    /// <summary> 
    /// Udpate State Machine once per frame.
    /// </summary>
    void Update()
    {
        if(isPasue)
            return;
        if (CURRENT_STATE != NEXT_STATE)
        {
            Debug.Log (CURRENT_STATE + "->" + NEXT_STATE);
        //	Debug.Log (m_InnerSate);
            CURRENT_STATE = NEXT_STATE;
        }
        if(Input.GetKeyDown(KeyCode.Alpha0) )
            Debug.Log (CURRENT_STATE);

        // Main Game Body.
        switch (CURRENT_STATE)
        {

        case STATE.GS_IDLE:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                if(!GameVariables.Instance.IS_FREEGAME && FreeGame.Instance.IsGMTransition)
                {
                    FreeGame.Instance.FreeGameEnd();
                }
                m_InnerSate = INNER_STATE.IS_UPDATE;
                break;

            case INNER_STATE.IS_UPDATE:

                //! Still play animation after last spin of feature game.
                //! function inside will self check validation
                if(FreeGame.Instance.IsExitFreeGame())
                {
                    LineAnim.Instance.DrawPlayLines();
                    IconAnim.Instance.PlayAnimation();
                }
                //Check Player Input when Idle state, 3 cases:
                //1. update bet information accordingly.
                //2. start next spin ( main or free game)
                //3. Entry the combination test(editor) mode.
                InputManager.Instance.InputUpdate();
                if(FreeGame.Instance.IsGMTransition && !GameVariables.Instance.IS_FREEGAME  && InputManager.Instance.IsCountingFGwin != 3)
                {
                    m_TempNS = STATE.GS_COUNTING_FG;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                //Go to Main Game spin.
                else if(GameVariables.Instance.IS_SPIN  &&
                  		 !GameVariables.Instance.IS_FREEGAME)
                {
                    m_TempNS = STATE.GS_REEL_SPIN_NG;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                // press "j" to start free games.
                else if(GameVariables.Instance.IS_FREEGAME )
                     // || FreeGame.Instance.FG_COUNTER > 0))
                {
                    m_TempNS = STATE.GS_REEL_SPIN_FG;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                else if (GameVariables.Instance.EDITOR_FLAG  == GameVariables.EDIT_STATES.NG_IDLE)
                {
                    m_TempNS = STATE.GS_NG_EDITOR;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                if(NEXT_STATE == STATE.GS_COUNTING_FG)
                    PauseGame(1.8f);

                m_InnerSate = INNER_STATE.IS_ENTER;
                break;
            }
            break;

        case STATE.GS_COUNTING_FG:
            switch(m_InnerSate)
            {
                case INNER_STATE.IS_ENTER:
                m_InnerSate = INNER_STATE.IS_UPDATE;
                InputManager.Instance.IsCountingFGwin = 1; // reset this flag value.
                AnimManager.Instance.IsEndCounFG_Win = false;

                break;
                case INNER_STATE.IS_UPDATE:

                InputManager.Instance.CheckCountingStart();

                if(FreeGame.Instance.IsExitFreeGame())
                {
                    LineAnim.Instance.DrawPlayLines();
                    IconAnim.Instance.PlayAnimation();
                }

                if(InputManager.Instance.IsCountingFGwin == 3)
                {
                    m_TempNS = STATE.GS_IDLE;
                    m_InnerSate =INNER_STATE.IS_EXIT;

                }
                else if(InputManager.Instance.IsCountingFGwin == 2)
                {
                    AnimManager.Instance.CountUpFreeGameWin();
                }
                break;
            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                m_InnerSate = INNER_STATE.IS_ENTER;
                break;
            }
            break;
            // Mian Game Spin. Random genarate output.
        case STATE.GS_REEL_SPIN_NG:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                // Reset varaibles about counting free gaming win behaviour.
                if(InputManager.Instance.IsCountingFGwin == 3)
                {
                    FreeGame.Instance.IsGMTransition = false;
                    InputManager.Instance.IsCountingFGwin = 1;
                    AudioManager.Instance.StopSound("GameTransition");
                }

                // only update meters( amount from last spin) when new spinning happen.
                UpdateMeters();
                IconAnim.Instance.Reset();
                // Assign proper reel srtips(true -> Main game) to use.
                GameVariables.Instance.SetCurrentStrip (true);

                // reset head/tail index to intitial postion( spining function will use them).
                Icons.Instance.ResetTempHeadTail();

                Icons.Instance.GernerateResult();

                m_InnerSate = INNER_STATE.IS_UPDATE;
                break;

            case INNER_STATE.IS_UPDATE:
                if(!GameVariables.Instance.IS_SPIN)
                {	//if spin finshed , go to check win state.
                    m_TempNS = STATE.GS_CHECK_WIN;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                else
                {
                    Icons.Instance.SpinReels(false);
                }
                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                m_InnerSate = INNER_STATE.IS_ENTER;
                break;
            }
            break;

            //Notice: For WUXIA GAME, CONFIRM WIN WHEN STATE BECOME GS_CHECK_WIN
        case STATE.GS_CHECK_WIN:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                m_InnerSate = INNER_STATE.IS_UPDATE;
                break;
            case INNER_STATE.IS_UPDATE:
                // Go to Animation state if got win or trigger free games.
                if( WinManager.Instance.IsGameWin() || WinManager.Instance.IsTriggerFG () )
                {
                    m_TempNS = STATE.GS_WIN_ANIMATION;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                else
                {
                    FreeGame.Instance.CheckFreeGame();
                    m_TempNS = STATE.GS_IDLE;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }

                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                m_InnerSate = INNER_STATE.IS_ENTER;
                break;
            }
            break;

            // Come to this state means we have won the current game.
            // so beside the animtaion behaviour, we also need to handle some win/bet amount update.
        case STATE.GS_WIN_ANIMATION:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:

                //update total credit(store to varaibles) but not update meters at this stage.
                // The meters only updated at the starting of next spin.
                WinManager.Instance.ComputeTotalWin(GameVariables.Instance.BET_PER_LINE);
                    if(!GameVariables.Instance.IS_FREEGAME && !GameVariables.Instance.IsThreeScatters())
                    GameVariables.Instance.SetCurrentCredit  (GameVariables.Instance.GetCurrentCredit() + WinManager.Instance.TOTALWIN);

        //				Debug.Log("Current Win :  " + GameVariables.Instance.GetCurrentCredit());
                m_InnerSate = INNER_STATE.IS_UPDATE;
                break;

            case INNER_STATE.IS_UPDATE:

                if(GameVariables.Instance.EDITOR_FLAG == GameVariables.EDIT_STATES.NG_IDLE)
                {
                    m_TempNS = STATE.GS_NG_EDITOR;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                //Animation will not end(in Main Game)untill some skip input detected.
                // In free game, either skip input or finishing win amount increasment will trigger Animation ending.
                // Then go to take win state.
                if(AnimManager.Instance.m_IsEnd)
                {
                    m_TempNS = STATE.GS_TAKE_WIN;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                else
                {

                    AnimManager.Instance.UpdateAnimation();
                }
                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                //Reset animation related variables.
                AnimManager.Instance.m_IsEnd = false;
                LineAnim.Instance.ResetIconsAlpha();
                IconAnim.Instance.HideAnimIcons();
                GameVariables.Instance.IS_INCRESED = false;

                AnimManager.Instance.IsPlayBigWin = false;
                GoldCoinEmitter.Instance.StopGoldCoinAnimation();

                m_InnerSate = INNER_STATE.IS_ENTER;
                break;
            }
            break;
            //Animation state is over, there are some win amount update in meter.
            // this state will show that win amount for seconds and decide which type of spin to go for next game.
        case STATE.GS_TAKE_WIN:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                m_InnerSate = INNER_STATE.IS_UPDATE;

                //! Move from free game spin enter state.
                //! if retrigger , it is a win also, so it must come to take win state.
                //! And we need to update free game left counter before checkFreegame function called.
                if (WinManager.Instance.IsTriggerFG())
                {
                    FreeGame.Instance.FG_LEFT += FreeGame.Instance.NUM_OF_FGS;
                    TextAndDigitDisp.Instance.IS_COUNTEND = false;
                    Icons.Instance.SetFirstFreeGameResult();
                    FreeGame.Instance.CheckFreeGame();
                }
                else
                {
                    FreeGame.Instance.CheckFreeGame();
                }

                break;
            case INNER_STATE.IS_UPDATE:

                // Pause game for showing win amount
                if ( (m_WinShowTime -= Time.deltaTime) < 0 )
                {
                    m_InnerSate = INNER_STATE.IS_EXIT;
                    //if game switch from free game to main game and player doesn't skip the last free game animation.
                    //The game will become idle state and waiting for input.
                    if(FreeGame.Instance.IsGMTransition)
                        m_TempNS = STATE.GS_IDLE;
                    else if(GameVariables.Instance.IS_FREEGAME )
                        m_TempNS = STATE.GS_REEL_SPIN_FG;
                    else if(!GameVariables.Instance.IS_FREEGAME )// && FreeGame.Instance.IsGMTransition )
                        m_TempNS = STATE.GS_REEL_SPIN_NG;
                }
                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                //reset win amount show time.
                m_WinShowTime = GameVariables.SHOW_WIN_TIME;
                m_InnerSate = INNER_STATE.IS_ENTER;

                //only case: exit from free game and free game got win.
                if(!GameVariables.Instance.IS_FREEGAME && NEXT_STATE == STATE.GS_IDLE)
                {
                    PauseGame(1.5f);
                }
                break;
            }
            break;

            //Only in idle state, editor input detected will entry this main game editor.
        case STATE.GS_NG_EDITOR:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                NgEditor.Instance.NgInitEditor();
                m_InnerSate = INNER_STATE.IS_UPDATE;

                break;
            case INNER_STATE.IS_UPDATE:

                NgEditor.Instance.ControlUpdate();
                //From main game editor , will go to either main game or free game editor.
                //But for WuXia, no more free game editor. since it's free game use different flowchat from others.
                if(GameVariables.Instance.EDITOR_FLAG == GameVariables.EDIT_STATES.NG_WAIT_TO_SPIN)
                {
                    m_TempNS = STATE.GS_IDLE;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                if(GameVariables.Instance.EDITOR_FLAG == GameVariables.EDIT_STATES.FG_IDLE)
                {
                    m_TempNS = STATE.GS_FG_EDITOR;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }

                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                m_InnerSate = INNER_STATE.IS_ENTER;
                break;
            }
            break;

        case STATE.GS_FG_EDITOR:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                //re-render different layout base on different reel strip.
                FgEditor.Instance.InitFreeGameEditor();
                m_InnerSate = INNER_STATE.IS_UPDATE;
                break;
            case INNER_STATE.IS_UPDATE:
                FgEditor.Instance.UpdateFGEditor();
                if(GameVariables.Instance.EDITOR_FLAG  == GameVariables.EDIT_STATES.FG_EDIT_END)
                {
                    m_TempNS = STATE.GS_IDLE;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                m_InnerSate = INNER_STATE.IS_ENTER;

                //it will spin first editer main game after exiting from free game editor.
                GameVariables.Instance.EDITOR_FLAG = GameVariables.EDIT_STATES.NG_WAIT_TO_SPIN;
                break;
            }
            break;

        case STATE.GS_REEL_SPIN_FG:
            switch(m_InnerSate)
            {
            case INNER_STATE.IS_ENTER:
                IconAnim.Instance.Reset();
                GameVariables.Instance.IS_SPIN = true;
                //change reel strips to free game's.
                GameVariables.Instance.SetCurrentStrip (false);
                // reset head/tail index to intitial postion.
                Icons.Instance.ResetTempHeadTail();
                m_InnerSate = INNER_STATE.IS_UPDATE;

                //! shoud check if free game is edited.
                Icons.Instance.GernerateResult();

                break;

            case INNER_STATE.IS_UPDATE:

                TextAndDigitDisp.Instance.CountingUpFGS();
                //				Debug.Log(TextAndDigitDisp.Instance.IS_COUNTEND);

                if(!TextAndDigitDisp.Instance.IS_COUNTEND)
                    return;

                TextAndDigitDisp.Instance.ShowLeftGames();
                // spin fnish
                if(!GameVariables.Instance.IS_SPIN)
                {

                    m_TempNS = STATE.GS_CHECK_WIN;
                    m_InnerSate = INNER_STATE.IS_EXIT;
                }
                else
                {

                //	Debug.Log(FreeGame.Instance.FG_ID);
                    Icons.Instance.SpinReels(true, (short)(FreeGame.Instance.FG_ID));
                }
                break;

            case INNER_STATE.IS_EXIT:
                NEXT_STATE = m_TempNS;
                if(NEXT_STATE == STATE.GS_IDLE)
                    PauseGame(1.5f);
                else
                    PauseGame(0.5f);

                m_InnerSate = INNER_STATE.IS_ENTER;
                break;
            }
            break;
        }// end of State machine
    }