public MenuItem Move(int answerId)
        {
            if (IsFinished)
            {
                return(_currentItem);
            }

            if (_currentItem.Type != MenuItemType.Checkpoint)
            {
                // save answer to history
                _history.Add(new HistoryItem(_currentItem.Id, answerId));
            }

            // check if menu closed
            if (answerId == Constants.MenuCloseLink &&
                _currentItem.Type == MenuItemType.Menu)
            {
                if (_previousItem == null)
                {
                    // if previous item not found, go to start item
                    _currentItem = _startItem;

                    OnMovedToNextStep?.Invoke(this, null, _currentItem);
                    return(_currentItem);
                }
                else
                {
                    // if previous item found, go to it
                    var prev = _previousItem;
                    _previousItem = _currentItem;
                    _currentItem  = prev;
                    OnMovedToNextStep?.Invoke(this, _previousItem, _currentItem);

                    return(_currentItem);
                }
            }

            // check if trying to pass checkpoint
            answerId = TryPassCheckpoint(answerId);

            // normal move - find next item id
            int nextId = _currentItem.GetNextItemId(answerId);

            if (nextId == Constants.NoLink)
            {
                IsFinished    = true;
                _previousItem = _currentItem;
                _currentItem  = null;

                OnMovedToNextStep?.Invoke(this, _previousItem, _currentItem);
                return(null);
            }

            // find next item
            var nextItem = _items.FirstOrDefault(i => i.Id == nextId);

            if (nextItem == null)
            {
                throw new ArgumentException($"There is no item with id {nextId} (answer id {answerId}).");
            }

            // save previous item
            _previousItem = _currentItem;
            // and change current to next
            _currentItem = nextItem;

            if (_currentItem.Answers.Any() == false)
            {
                // sequence is finished if there is no answers for current item
                IsFinished = true;
            }

            // invoke handler if it's set
            OnMovedToNextStep?.Invoke(this, _previousItem, _currentItem);

            if (_currentItem.Type == MenuItemType.Checkpoint)
            {
                // if we reach checkpoint, call handers automatically
                _currentItem = Move(0);
            }

            return(_currentItem);
        }
        public MenuItem Move(int answerId)
        {
            if (IsFinished)
            {
                return(_currentItem);
            }

            if (_currentItem.Type != MenuItemType.Checkpoint)
            {
                _history.Add(new HistoryItem(_currentItem.Id, answerId));
            }

            if (answerId == Constants.MenuCloseLink &&
                _currentItem.Type == MenuItemType.Menu)
            {
                if (_previousItem == null)
                {
                    _currentItem = _startItem;

                    OnMovedToNextStep?.Invoke(Client, null, _currentItem);
                    return(_currentItem);
                }

                var prev = _previousItem;
                _previousItem = _currentItem;
                _currentItem  = prev;
                OnMovedToNextStep?.Invoke(Client, _previousItem, _currentItem);

                return(_currentItem);
            }

            answerId = TryPassCheckpoint(answerId);

            var nextId = _currentItem.GetNextItemId(answerId);

            if (nextId == Constants.NoLink)
            {
                IsFinished    = true;
                _previousItem = _currentItem;
                _currentItem  = null;

                OnMovedToNextStep?.Invoke(Client, _previousItem, _currentItem);
                return(null);
            }

            var nextItem = _items.FirstOrDefault(i => i.Id == nextId);

            if (nextItem == null)
            {
                return(null);
            }

            _previousItem = _currentItem;
            _currentItem  = nextItem;

            if (_currentItem.Answers.Any() == false)
            {
                IsFinished = true;
            }

            OnMovedToNextStep?.Invoke(Client, _previousItem, _currentItem);

            AutoPassCheckpoint();

            return(_currentItem);
        }
        public MenuItem Move(int answerId)
        {
            if (IsFinished)
            {
                return(_currentItem);
            }

            if (_currentItem.Type != MenuItemType.Checkpoint)
            {
                // save answer to history
                _history.Add(new HistoryItem(_currentItem.Id, answerId));
            }

            // check if menu closed
            if (answerId == Constants.MenuCloseLink &&
                _currentItem.Type == MenuItemType.Menu)
            {
                if (_previousItem == null)
                {
                    // if previous item not found, go to start item
                    _currentItem = _startItem;

                    OnMovedToNextStep?.Invoke(Client, null, _currentItem);
                    return(_currentItem);
                }

                // if previous item found, go to it
                var prev = _previousItem;
                _previousItem = _currentItem;
                _currentItem  = prev;
                OnMovedToNextStep?.Invoke(Client, _previousItem, _currentItem);

                return(_currentItem);
            }

            // check if trying to pass checkpoint
            answerId = TryPassCheckpoint(answerId);

            // normal move - find next item id
            var nextId = _currentItem.GetNextItemId(answerId);

            if (nextId == Constants.NoLink)
            {
                IsFinished    = true;
                _previousItem = _currentItem;
                _currentItem  = null;

                OnMovedToNextStep?.Invoke(Client, _previousItem, _currentItem);
                return(null);
            }

            // find next item
            var nextItem = _items.FirstOrDefault(i => i.Id == nextId);

            if (nextItem == null)
            {
                return(null);
            }

            // save previous item
            _previousItem = _currentItem;
            // and change current to next
            _currentItem = nextItem;

            if (_currentItem.Answers.Any() == false)
            {
                // sequence is finished if there is no answers for current item
                IsFinished = true;
            }

            // invoke handler if it's set
            OnMovedToNextStep?.Invoke(Client, _previousItem, _currentItem);

            // auto pass checkpoint if necessary
            AutoPassCheckpoint();

            return(_currentItem);
        }