// This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddBot<TestBot>(options =>
            {
                IStorage dataStore = new MemoryStorage();
                options.State.Add(new ConversationState(dataStore));
                options.Middleware.Add(new AutoSaveStateMiddleware(options.State.ToArray()));
                //options.Middleware.Add(new ShowTypingMiddleware());

                var secretKey = Configuration.GetSection("botFileSecret")?.Value;
                var botFilePath = Configuration.GetSection("botFilePath")?.Value;

                // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
                var botConfig = BotConfiguration.Load(botFilePath ?? @".\BotConfiguration.bot", secretKey);
                services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded. ({botConfig})"));

                // Retrieve current endpoint.
                var environment = _isProduction ? "production" : "development";
                var service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == environment).FirstOrDefault();
                if (!(service is EndpointService endpointService))
                {
                    throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
                }

                options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
            });

            services.AddSingleton(sp =>
            {
                var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;
                if (options == null)
                {
                    throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors");
                }

                var conversationState = options.State.OfType<ConversationState>().FirstOrDefault();
                if (conversationState == null)
                {
                    throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors.");
                }

                var accessors = new TestBotAccessors
                {
                    ConversationDialogState = conversationState.CreateProperty<DialogState>("DialogState")
                };

                return accessors;
            });
        }
        public TestBot(TestBotAccessors accessors)
        {
            // create the DialogSet from accessor
            _dialogs = new DialogSet(accessors.ConversationDialogState);

            // a semaphore to serialize access to the bot state
            _semaphore = accessors.SemaphoreSlim;

            // add the various named dialogs that can be used
            _dialogs.Add(new MenuDialog());
            _dialogs.Add(FormDialog.FromForm(Order.BuildOrderForm));
            _dialogs.Add(FormDialog.FromForm(SandwichOrder.BuildForm));
            _dialogs.Add(FormDialog.FromForm(BuilderSandwich.BuildForm));
            _dialogs.Add(FormDialog.FromForm(() => PizzaOrder.BuildForm(localize: true)));
            _dialogs.Add(FormDialog.FromForm(ScheduleCallbackDialog.BuildForm));
            _dialogs.Add(FormDialog.FromForm(ImagesForm.BuildForm));
            _dialogs.Add(new HotelsDialog()); //<--loads a FormFlow dialog and does processing with the results
        }