private bool MoveToNext()

in CSharp/Library/Microsoft.Bot.Builder/FormFlow/FormDialog.cs [577:774]


        private bool MoveToNext(NextStep next)
        {
            bool found = false;
            switch (next.Direction)
            {
                case StepDirection.Complete:
                    break;
                case StepDirection.Named:
                    _formState.StepState = null;
                    if (next.Names.Length == 0)
                    {
                        goto case StepDirection.Next;
                    }
                    else if (next.Names.Length == 1)
                    {
                        var name = next.Names.First();
                        var nextStep = -1;
                        for (var i = 0; i < _form.Steps.Count(); ++i)
                        {
                            if (_form.Steps[i].Name == name)
                            {
                                nextStep = i;
                                break;
                            }
                        }
                        if (nextStep == -1)
                        {
                            throw new ArgumentOutOfRangeException("NextStep", "Does not correspond to a field in the form.");
                        }
                        if (_form.Steps[nextStep].Active(_state))
                        {
                            var current = _form.Steps[_formState.Step];
                            _formState.SetPhase(_form.Fields.Field(current.Name).IsUnknown(_state) ? StepPhase.Ready : StepPhase.Completed);
                            _formState.History.Push(_formState.Step);
                            _formState.Step = nextStep;
                            _formState.SetPhase(StepPhase.Ready);
                            found = true;
                        }
                        else
                        {
                            // If we went to a state which is not active fall through to the next active if any
                            goto case StepDirection.Next;
                        }
                    }
                    else
                    {
                        // Always mark multiple names as found so we can handle the user navigation
                        found = true;
                    }
                    break;
                case StepDirection.Next:
                    {
                        var start = _formState.Step;
                        // Reset any non-optional field step that has been reset to no value
                        for (var i = 0; i < _form.Steps.Count; ++i)
                        {
                            var step = _form.Steps[i];
                            if (step.Type == StepType.Field && _formState.Phase(i) == StepPhase.Completed && !step.Field.Optional && step.Field.IsUnknown(_state))
                            {
                                _formState.SetPhase(i, StepPhase.Ready);
                            }
                        }
                        // Next ready step including current one
                        for (var offset = 0; offset < _form.Steps.Count; ++offset)
                        {
                            var istep = (start + offset) % _form.Steps.Count;
                            var step = _form.Steps[istep];
                            _formState.Step = istep;
                            if (offset > 0)
                            {
                                _formState.StepState = null;
                                _formState.Next = null;
                            }
                            if ((_formState.Phase(istep) == StepPhase.Ready || _formState.Phase(istep) == StepPhase.Responding)
                                && step.Active(_state))
                            {
                                // Ensure all dependencies have values
                                foreach (var dependency in step.Dependencies)
                                {
                                    var dstep = _form.Step(dependency);
                                    var dstepi = _form.StepIndex(dstep);
                                    if (dstep.Active(_state) && _formState.Phases[dstepi] != StepPhase.Completed)
                                    {
                                        _formState.Step = dstepi;
                                        break;
                                    }
                                }
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            next.Direction = StepDirection.Complete;
                        }
                        else
                        {
                            var normalStep = _formState.Step;
                            // Process initial messages first, then FieldInputs
                            if ((_formState.ProcessInputs || _form.Steps[normalStep].Type != StepType.Message) && _formState.FieldInputs != null)
                            {
                                // Override normal choice with FieldInputs
                                Func<bool> NextFieldInput = () =>
                                {
                                    var foundInput = false;
                                    while (_formState.FieldInputs.Any() && !foundInput)
                                    {
                                        var possible = _formState.FieldInputs.Last().Item1;
                                        if (_form.Steps[possible].Active(_state))
                                        {
                                            _formState.Step = possible;
                                            foundInput = true;
                                        }
                                        else
                                        {
                                            _formState.FieldInputs.Pop();
                                        }
                                    }
                                    if (!_formState.FieldInputs.Any())
                                    {
                                        if (_options.HasFlag(FormOptions.PromptFieldsWithValues))
                                        {
                                            _formState.Reset();
                                        }
                                        else
                                        {
                                            _formState.ProcessInputs = false;
                                            _formState.FieldInputs = null;
                                            _formState.Step = 0;
                                        }
                                        // Skip initial messages since we showed them already
                                        while (_formState.Step < _form.Steps.Count() && _form.Steps[_formState.Step].Type == StepType.Message)
                                        {
                                            _formState.SetPhase(StepPhase.Completed);
                                            ++_formState.Step;
                                        }
                                    }
                                    return foundInput;
                                };
                                if (!_formState.ProcessInputs)
                                {
                                    // Start of processing inputs
                                    _formState.ProcessInputs = NextFieldInput();
                                }
                                else if (_formState.Phase(start) == StepPhase.Completed || _formState.Phase(start) == StepPhase.Ready)
                                {
                                    // Reset state of just completed step
                                    if (_options.HasFlag(FormOptions.PromptFieldsWithValues))
                                    {
                                        _formState.SetPhase(StepPhase.Ready);
                                    }
                                    // Move on to next field input if any
                                    _formState.FieldInputs.Pop();
                                    NextFieldInput();
                                }
                            }
                            else
                            {
                                if (_formState.Step != start && _form.Steps[start].Type != StepType.Message)
                                {
                                    _formState.History.Push(start);
                                }
                            }
                        }
                    }
                    break;
                case StepDirection.Previous:
                    while (_formState.History.Count() > 0)
                    {
                        var lastStepIndex = _formState.History.Pop();
                        var lastStep = _form.Steps[lastStepIndex];
                        if (lastStep.Active(_state))
                        {
                            var step = _form.Steps[_formState.Step];
                            _formState.SetPhase(step.Field.IsUnknown(_state) ? StepPhase.Ready : StepPhase.Completed);
                            _formState.Step = lastStepIndex;
                            _formState.SetPhase(StepPhase.Ready);
                            _formState.StepState = null;
                            _formState.Next = null;
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        next.Direction = StepDirection.Quit;
                    }
                    break;
                case StepDirection.Quit:
                    break;
                case StepDirection.Reset:
                    _formState.Reset();
                    // Because we redo phase they can go through everything again but with defaults.
                    found = true;
                    break;
            }
            return found;
        }