/// <summary>
        /// This step shows how a simple text prompts works
        /// </summary>
        /// <remarks>
        /// To see sample code for other prompt types: https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-compositcontrol?view=azure-bot-service-4.0&tabs=csharp
        /// </remarks>
        public async Task <DialogTurnResult> AskForName(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            // Get converation state so we can check to see if name has already been provided
            _state = await _accessor.GetAsync(sc.Context, () => new MembershipState());

            await sc.Context.SendActivityAsync("I can help you get a library card!");

            // If first name has already been provided
            if (!string.IsNullOrEmpty(_state.Name))
            {
                // Skip this step and pass first name to next step
                return(await sc.NextAsync(_state.Name));
            }
            else
            {
                return(await sc.PromptAsync(DialogIds.NamePrompt, new PromptOptions
                {
                    Prompt = MessageFactory.Text("What's your name?")
                }));

                // To localize a multilingual bot, use the approach below instead of the one above
                //return await sc.PromptAsync(DialogIds.NamePrompt, new PromptOptions()
                //{
                //    Prompt = await _responder.RenderTemplate(sc.Context, sc.Context.Activity.Locale, OnboardingResponses.ResponseIds.NamePrompt),
                //});
            }
        }
        /// <summary>
        /// This step shows how bot can creatively tie into existing business process (email in this case)
        /// </summary>
        /// <remarks>
        /// This step shows how a bot might integrate with an existing business process
        /// that is email based to verify a code that is sent to the bot user.  It's
        /// another example of leveraging custom validation.
        /// </remarks>
        public async Task <DialogTurnResult> GetVerificationCode(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            // Get conversation state so we can have access to email that was provided previously
            _state = await _accessor.GetAsync(sc.Context, () => new MembershipState());

            return(await sc.PromptAsync(DialogIds.VerificationPrompt, new PromptOptions
            {
                Prompt = MessageFactory.Text($"We've sent a verification email to {_state.Email}.  Please enter the verification code"),
                // Provide retry prompt for custom verification code validation for TextPrompt
                RetryPrompt = MessageFactory.Text("Sorry, that is an invalid verification code. Please check code and try again.")
            }));
        }
        /// <summary>
        /// The last step sums up the conversation
        /// </summary>
        /// <remarks>
        /// The last step in a dialog generally sums up the conversation and
        /// performs an action that achieves the goal of the conversation which
        /// in this example would be to call a back end service to create a
        /// library membership for the user and send them a confirmation email.
        /// </remarks>
        public async Task <DialogTurnResult> FinishGetLibraryCardDialog(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            _state = await _accessor.GetAsync(sc.Context, () => new MembershipState());

            // Save the answer from the previous step in conversation state
            string verificationCode = (string)sc.Result;

            // Provide summary of conversation for this dialog
            await sc.Context.SendActivityAsync($"We're all set {_state.Name}!  A confirmation will all your membership details will be emailed to {_state.Email}");

            // ToDo Phase 2 - Step 01: Perform goal of conversation here (call membership service in this case)
            // libraryService.CreateMembership(_state);

            return(await sc.EndDialogAsync());
        }
        /// <summary>
        /// Silent branching step to decide what direction the conversation should go
        /// </summary>
        /// <remarks>
        /// This step shows another example of how to manage conversation flow.
        /// It's also interesting in that its a step without an associatede dialog
        /// prompt so its sole job is deciding how to proceed given the current
        /// context/state of the conversation (i.e. end dialog or continue to
        /// next step)
        ///
        /// To test the "end dialog" branch, enter "already@member" when asked for
        /// email.
        /// </remarks>
        public async Task <DialogTurnResult> CheckIfAlreadyMember(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            _state = await _accessor.GetAsync(sc.Context, () => new MembershipState());

            // Save the answer from the previous step in conversation state
            _state.Email = (string)sc.Result;
            await _accessor.SetAsync(sc.Context, _state, cancellationToken);

            if (_state.Email == "already@member")
            {
                await sc.Context.SendActivityAsync($"Looks like you already have a library card.  We'll send your membership information to {_state.Email}");

                return(await sc.EndDialogAsync());
            }
            else
            {
                // We can safely move to next next step
                return(await sc.NextAsync());
            }
        }
        /// <summary>
        /// This step shows how to provide a custom retry prompt for custom validation
        /// </summary>
        /// <remarks>
        /// Other than providing the custom retry prompt, this step is just another
        /// example of a simple prompt
        /// </remarks>
        public async Task <DialogTurnResult> AskForEmail(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            _state = await _accessor.GetAsync(sc.Context, () => new MembershipState());

            // Save the answer from the previous step in conversation state
            _state.Age = (int)sc.Result;
            await _accessor.SetAsync(sc.Context, _state, cancellationToken);

            if (!string.IsNullOrEmpty(_state.Email))
            {
                // Skip this step and pass email to next step
                return(await sc.NextAsync(_state.Email));
            }
            else
            {
                return(await sc.PromptAsync(DialogIds.EmailPrompt, new PromptOptions
                {
                    Prompt = MessageFactory.Text("What is your email?"),
                    // Provide retry prompt for custom email validation on a TextPrompt
                    RetryPrompt = MessageFactory.Text("That's not a valid email address, please try again")
                }));
            }
        }
        /// <summary>
        /// This step shows how to code a numeric prompt which shows an example of
        /// the framework's built-in validation
        /// </summary>
        /// <remarks>
        /// The built-in validation for a NumberPrompt<int> will only accept an integer
        /// so you can enter any non-integer value to see the built-in validation in action
        /// </remarks>
        public async Task <DialogTurnResult> AskForAge(WaterfallStepContext sc, CancellationToken cancellationToken)
        {
            _state = await _accessor.GetAsync(sc.Context, () => new MembershipState());

            // Save the answer from the previous step in conversation state
            _state.Name = (string)sc.Result;
            await _accessor.SetAsync(sc.Context, _state, cancellationToken);

            // If age has already been provided
            if (_state.Age != 0)
            {
                // Skip this step and pass age to next step
                return(await sc.NextAsync(_state.Age));
            }
            else
            {
                return(await sc.PromptAsync(DialogIds.AgePrompt, new PromptOptions
                {
                    Prompt = MessageFactory.Text("How old are you?"),
                    // Override the built-in integer retry prompt with a scenario-friendly one
                    RetryPrompt = MessageFactory.Text("Please enter age as an integer")
                }));
            }
        }