public void CancelTransition()
        {
            //todo next sstate intransition
            if (!IsInTransition)
            {
                return;
            }

            if (_currentState != null && !_currentState.HasExitRoutine)
            {
                Debug.Log("Current State doesn't have Exiting Routine.. you cannot cancel it");
                return;
            }
            else if (_currentState != null && _currentState.HasExitRoutine)
            {
                if (!_currentState.IsInTransition.Value)
                {
                    _currentState.ExitCancel.Invoke();
                }
                _queHistory.Cancle();
                return;
            }

            _queHistory.Cancle();
            _StateInQeue = null;
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="component"> the subscriber </param>
        /// <exception cref="ArgumentException"> Enum provided to Initialize must have at least 1 visible definition </exception>
        public StateMachine(MonoBehaviour component)
        {
            //to track what is running state
            _stateStream.Subscribe(st =>
            {
                //StateStream.OnNext(st.GetState());
                if (Changed != null)
                {
                    Changed.Invoke(st.GetState());
                }
                if (_tempStates.Count < 1)
                {
                    _currentState = st;
                    _tempStates.Enqueue(_currentState);
                }
                else
                {
                    _lastState    = _tempStates.Dequeue();
                    _currentState = st;
                    _tempStates.Enqueue(_currentState);
                }
            }).AddTo(component);
            _component = component;

            //Define States
            var values = Enum.GetValues(typeof(T));

            if (values.Length < 1)
            {
                throw new ArgumentException("Enum provided to Initialize must have at least 1 visible definition");
            }
            _stateLookup = new Dictionary <object, StateMapping>();
            for (int i = 0; i < values.Length; i++)
            {
                var mapping = new StateMapping((Enum)values.GetValue(i), _stateStream);
                _stateLookup.Add(mapping.GetState(), mapping);
            }

            AddSubscriber_Internal(component);
            _initNotifyer.OnNext(Unit.Default);
            _initNotifyer.OnCompleted();
        }
        private void ChangeStateInternal(T newState, StateTransition transition, float enterDuration, float exitDuration)
        {
            if (_stateLookup == null)
            {
                throw new Exception("States have not been configured, please call initialized before trying to set state");
            }

            if (!_stateLookup.ContainsKey(newState))
            {
                throw new Exception("No state with the name " + newState.ToString() +
                                    " can be found. Please make sure you are called the correct type the statemachine was initialized with");
            }

            var nextState = _stateLookup[newState];

            if (_currentState != null && _currentState == nextState)
            {
                return;
            }
            //if (_StateInQeue != null && _StateInQeue == nextState) return;

            if (transition.Equals(StateTransition.Safe))
            {
                if (_currentState == null)                         //for initial run
                {
                    _queHistory.Add(nextState.CreateNewRoutine(nextState.HasEnterRoutine ? enterDuration : 0f, true));
                    _StateInQeue = nextState;
                    return;
                }

                if (_currentState.ExitInQue)                        //if current one has exit routine waiting
                {
                    _queHistory.Add(_currentState.CreateNewRoutine(_currentState.HasExitRoutine ? exitDuration : 0f, false));
                    _queHistory.Add(nextState.CreateNewRoutine(nextState.HasEnterRoutine ? enterDuration : 0f, true));
                    _StateInQeue = nextState;
                }
                else                                                           //already in current  exit routine
                {
                    if (!_StateInQeue.GetState().Equals(nextState.GetState())) //if next state is not in qeue
                    {
                        _queHistory.Add(nextState.CreateNewRoutine(nextState.HasEnterRoutine ? enterDuration : 0f, true));
                        _StateInQeue = nextState;
                    }
                }
            }
            else if (transition.Equals(StateTransition.Overwrite))
            {
                if (_currentState == null)                         //for initial run
                {
                    _queHistory.Add(nextState.CreateNewRoutine(nextState.HasEnterRoutine ? enterDuration : 0f, true));
                    _StateInQeue = nextState;
                }
                else
                {
                    //todo test more on OnCancle.Invoke
                    //_StateInQeue.EnterCancel.Invoke();
                    _queHistory.Cancle();
                    _currentState.Finally.Invoke();

                    _queHistory.Add(nextState.CreateNewRoutine(nextState.HasEnterRoutine ? enterDuration : 0f, true));
                    _StateInQeue = nextState;
                }
            }
            else                           //blend
            {
                if (_currentState == null) //for initial run
                {
                    _queHistory.Add(nextState.CreateNewRoutine(nextState.HasEnterRoutine ? enterDuration : 0f, true));
                    _StateInQeue = nextState;
                    return;
                }
                if (_currentState.ExitInQue)                        //if current one has exit routine, waiting
                {
                    _queHistory.AddPair(_currentState.CreateNewRoutine(_currentState.HasExitRoutine ? exitDuration : 0f, false),
                                        nextState.CreateNewRoutine(nextState.HasEnterRoutine ? enterDuration : 0f, true));
                    _StateInQeue = nextState;
                }
            }
        }