private async Task <DialogTurnResult> CheckPromotions(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var recipeState = await UserProfileAccessor.GetAsync(stepContext.Context);

            // var resultConfirmationWantsToOrderFood = stepContext.Result as bool?;
            var resultConfirmationWantsToOrderFood = ParseSpokenBool(stepContext);

            if (resultConfirmationWantsToOrderFood.HasValue)
            {
                recipeState.DoNotOrderFood = !resultConfirmationWantsToOrderFood.Value;
                await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                if (!resultConfirmationWantsToOrderFood.Value)
                {
                    return(await stepContext.NextAsync());
                }
            }

            var recipe = new UStoreDBManagement(_context).GetRecipeOfTheWeek();

            if (recipe != null)
            {
                var ingredientsOfRecipeOfTheWeek = new UStoreDBManagement(_context).GetIngredientsFromRecipe(recipe.RecipeId);

                if (ingredientsOfRecipeOfTheWeek != null &&
                    ingredientsOfRecipeOfTheWeek.Count > 0)
                {
                    Models.Discount ingredientDiscount = null;

                    foreach (var item in ingredientsOfRecipeOfTheWeek)
                    {
                        ingredientDiscount = new UStoreDBManagement(_context).GetIngredientDiscount(item.IngredientId);

                        if (ingredientDiscount != null)
                        {
                            break;
                        }
                    }

                    // var ingredientDiscount = new UStoreDBManagement(_context).GetIngredientDiscount(ingredientsOfRecipeOfTheWeek[0].IngredientId);

                    if (ingredientDiscount != null)
                    {
                        string ingredientName = ingredientDiscount.Ingredient.Name;
                        double discount       = ingredientDiscount.DiscountPercentValue;

                        return(await stepContext.PromptAsync(DialogPromptIds.UserRecipeOfTheWeekPrompt, new PromptOptions()
                        {
                            Prompt = await _responder.RenderTemplate(stepContext.Context, stepContext.Context.Activity.Locale, RecipeResponses.ReceitasRespondeIds.RecipeOfTheWeekDialog, new { recipe.Name, discount, ingredientName }),
                        }));
                    }
                }
            }


            return(await stepContext.NextAsync());
        }
        private async Task <bool> ValidateRecipe(PromptValidatorContext <string> promptContext, CancellationToken cancellationToken)
        {
            var value  = promptContext.Recognized.Value?.Trim() ?? string.Empty;
            var recipe = new UStoreDBManagement(_context).GetRecipe(value);

            if (recipe != null)
            {
                promptContext.Recognized.Value = recipe.Name;
                return(true);
            }
            else
            {
                await _responder.ReplyWith(promptContext.Context, RecipeResponses.ReceitasRespondeIds.RecipeNotAvailable);

                return(false);
            }
        }
        private async Task <bool> SendMailApointment(RecipeState recipeState, DateTime timeDinner)
        {
            HttpClient client = new HttpClient();

            string strEmailBody = string.Empty;

            if (recipeState.OrderedIngredientsQuantities != null &&
                recipeState.OrderedIngredientsQuantities.Count > 0)
            {
                strEmailBody = "Hello there!\n\n" +
                               "Thank you for choosing UniShop to help you with your dinner arrangements.\n";

                if (recipeState.PeopleForDinner.HasValue)
                {
                    strEmailBody = string.Concat(strEmailBody, string.Format("We ordered food for you and your {0} friends.\n", recipeState.PeopleForDinner.Value));
                }

                if (recipeState.OrderPizza.HasValue && recipeState.OrderPizza.Value)
                {
                    strEmailBody = string.Concat(strEmailBody, "You ordered pizza for the dinner.\n\n");
                }
                else
                {
                    string straux = string.Format("\nYou ordered the following ingredients to cook the dish '{0}':\n", recipeState.Name);
                    strEmailBody = string.Concat(strEmailBody, straux);
                    foreach (var keyValuePairLoop in recipeState.OrderedIngredientsQuantities)
                    {
                        var ingredient = new UStoreDBManagement(_context).GetIngredientById(keyValuePairLoop.Key);
                        if (ingredient != null)
                        {
                            if (keyValuePairLoop.Value > 1)
                            {
                                straux       = string.Format("{0} {1}s\n", keyValuePairLoop.Value, ingredient.Name);
                                strEmailBody = string.Concat(strEmailBody, straux);
                            }
                            else
                            {
                                straux       = string.Format("{0} {1}\n", keyValuePairLoop.Value, ingredient.Name);
                                strEmailBody = string.Concat(strEmailBody, straux);
                            }
                        }
                    }
                }

                strEmailBody = string.Concat(strEmailBody, "\nHope you have a nice dinner!\n\nUniShop");
            }

            DateTime dtaux  = new DateTime(timeDinner.Year, timeDinner.Month, timeDinner.Day, 20, 0, 0);
            DateTime dtaux2 = new DateTime(timeDinner.Year, timeDinner.Month, timeDinner.Day, 23, 0, 0);

            string bodyAppointment = string.Empty;

            if (recipeState.PeopleForDinner.HasValue)
            {
                bodyAppointment = string.Format("Dinner with {0} friends.", recipeState.PeopleForDinner.Value.ToString());
            }

            Dictionary <string, string> data = new Dictionary <string, string>
            {
                { "createEmail", !string.IsNullOrEmpty(strEmailBody) ? "true" : "false" },
                { "emailTo", "*****@*****.**" },
                { "emailSubject", "UniShop - Order" },
                { "emailBody", strEmailBody },
                { "createAppointment", "true" },
                { "appointmentStartDate", dtaux.ToString("MM/dd/yyyy HH:mm:ss") },
                { "appointmentEndDate", dtaux2.ToString("MM/dd/yyyy  HH:mm:ss") },
                { "appointmentTitle", "Dinner with friends (by UniShop)" },
                { "appointmentBody", bodyAppointment },
            };

            string json        = JsonConvert.SerializeObject(data);
            var    httpContent = new StringContent(json, Encoding.UTF8, "application/json");

            using (HttpResponseMessage response = await client.PostAsync(logicApp, httpContent))
            {
            }

            return(true);
        }
        private async Task <DialogTurnResult> DisplayBillUser(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var context     = stepContext.Context;
            var recipeState = await UserProfileAccessor.GetAsync(stepContext.Context);

            if (recipeState.DoNotOrderFood.HasValue &&
                recipeState.DoNotOrderFood.Value)
            {
                return(await stepContext.NextAsync());
            }

            bool?resultConfirmationUseStorageItemsDialog = null;

            if (recipeState.OrderPizza.HasValue &&
                recipeState.OrderPizza.Value)
            {
                resultConfirmationUseStorageItemsDialog = true;
                recipeState.UseStoreRoomItems           = resultConfirmationUseStorageItemsDialog.Value;
                await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);
            }
            else
            {
                resultConfirmationUseStorageItemsDialog = ParseSpokenBool(stepContext);
                recipeState.UseStoreRoomItems           = resultConfirmationUseStorageItemsDialog.Value;
                await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);
            }

            if (resultConfirmationUseStorageItemsDialog.HasValue &&
                resultConfirmationUseStorageItemsDialog.Value &&
                recipeState.OrderedIngredientsQuantities != null &&
                recipeState.OrderedIngredientsQuantities.Count > 0)
            {
                await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.ProceedLogin);

                // CALCULAR TOTAL E PERGUNTAR SE PODE COMMIT TRANSACCAO

                Dictionary <int, int> necessaryIngredientsToBuy = recipeState.OrderedIngredientsQuantities;

                // calcular preço final
                double total = 0;

                if (recipeState.OrderPizza.HasValue &&
                    recipeState.OrderPizza.Value &&
                    recipeState.TotalPrice.HasValue)
                {
                    total = recipeState.TotalPrice.Value;
                }
                else
                {
                    foreach (var itemLoop in necessaryIngredientsToBuy)
                    {
                        var pricePerUnit = new UStoreDBManagement(_context).GetIngredientPricePerUnit(itemLoop.Key);
                        total += pricePerUnit * itemLoop.Value;
                    }

                    recipeState.TotalPrice = total;
                    recipeState.OrderedIngredientsQuantities = necessaryIngredientsToBuy;

                    // abrir carrinho de compras e colocar lá pedido
                    recipeState.CartId = new UStoreDBManagement(_context).CreateCart(necessaryIngredientsToBuy, total);

                    await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);
                }

                if (total > 0)
                {
                    return(await stepContext.PromptAsync(DialogPromptIds.ConfirmTotalPrice, new PromptOptions()
                    {
                        Prompt = await _responder.RenderTemplate(
                            stepContext.Context,
                            stepContext.Context.Activity.Locale,
                            RecipeResponses.ReceitasRespondeIds.ConfirmTotalPrice,
                            total.ToString()),
                    }));
                }
                else
                {
                    // não é suposto passar por aqui
                    // mandar msg a dizer q não precisa de comprar nada e terminar dialogo
                    await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.EnoughIngredientsStorage);

                    recipeState.CleanState();
                    await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                    await stepContext.CancelAllDialogsAsync();

                    return(await stepContext.EndDialogAsync());
                }
            }
            else if (recipeState.OrderPizza.HasValue &&
                     recipeState.OrderPizza.Value)
            {
                // encomendou pizza
                await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.ProceedLogin);

                return(await stepContext.PromptAsync(DialogPromptIds.ConfirmTotalPrice, new PromptOptions()
                {
                    Prompt = await _responder.RenderTemplate(
                        stepContext.Context,
                        stepContext.Context.Activity.Locale,
                        RecipeResponses.ReceitasRespondeIds.ConfirmTotalPrice,
                        recipeState.TotalPrice),
                }));
            }
            else
            {
                await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.UpdateCartLaterUse);

                // finalizar conversa
                recipeState.CleanState();
                await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                var evento = Activity.CreateEndOfConversationActivity();
                await stepContext.Context.SendActivityAsync(evento);

                return(await stepContext.EndDialogAsync());
            }
        }
        private async Task <DialogTurnResult> DisplayNecessaryIngredientsListAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var recipeState = await UserProfileAccessor.GetAsync(stepContext.Context);

            if (recipeState.DoNotOrderFood.HasValue &&
                recipeState.DoNotOrderFood.Value)
            {
                return(await stepContext.NextAsync());
            }

            if (recipeState.OrderPizza.HasValue && recipeState.OrderPizza.Value)
            {
                return(await stepContext.NextAsync());
            }

            int?numPersons = stepContext.Result as int?;

            if (!recipeState.PeopleForDinner.HasValue && numPersons.HasValue)
            {
                recipeState.PeopleForDinner = numPersons.Value;
            }

            var context = stepContext.Context;

            var ingredients    = new UStoreDBManagement(_context).GetIngredientsFromRecipe(recipeState.Name);
            var storeRoomItems = new UStoreDBManagement(_context).GetStoreRoomItems();

            if (ingredients != null && ingredients.Count > 0)
            {
                var recipe = new UStoreDBManagement(_context).GetRecipe(recipeState.Name);

                Dictionary <int, int> orderedIngredientsQuantities = new Dictionary <int, int>();

                await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.NecessaryIngredients);

                foreach (Ingredient ingredientLoop in ingredients)
                {
                    if (!string.IsNullOrEmpty(ingredientLoop.Name))
                    {
                        int?quantityPerPerson = new UStoreDBManagement(_context).GetNecessaryIngredientForRecipe(recipe.RecipeId, ingredientLoop.IngredientId);
                        int?quantity          = null;
                        if (quantityPerPerson.HasValue)
                        {
                            quantity = quantityPerPerson.Value * recipeState.PeopleForDinner.Value;
                        }

                        // verificar se existe em despensa e subtrair à quantidade necessária
                        if (storeRoomItems != null)
                        {
                            var abc = storeRoomItems.Find(st => st.Ingredient != null &&
                                                          st.Ingredient.IngredientId == ingredientLoop.IngredientId);

                            if (abc != null && abc.Quantity > 0)
                            {
                                quantity -= abc.Quantity;
                            }
                        }

                        string strIngredientMsg = string.Empty;

                        if (quantity != null && quantity.HasValue && quantity > 0)
                        {
                            await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                            if (quantity.Value > 1)
                            {
                                strIngredientMsg = quantity.ToString() + " " + ingredientLoop.Name + "s";
                            }
                            else
                            {
                                strIngredientMsg = quantity.ToString() + " " + ingredientLoop.Name;
                            }

                            orderedIngredientsQuantities.Add(ingredientLoop.IngredientId, quantity.Value);

                            await stepContext.Context.SendActivityAsync(strIngredientMsg, strIngredientMsg, InputHints.IgnoringInput);
                        }
                        //else
                        //{
                        //    await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                        //    strIngredientMsg = ingredientLoop.Name;
                        //}
                    }
                }

                if (orderedIngredientsQuantities.Count > 0)
                {
                    recipeState.OrderedIngredientsQuantities = orderedIngredientsQuantities;
                    await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);
                }

                return(await stepContext.PromptAsync(DialogPromptIds.ConfirmRecipePrompt, new PromptOptions()
                {
                    Prompt = await _responder.RenderTemplate(
                        stepContext.Context,
                        stepContext.Context.Activity.Locale,
                        RecipeResponses.ReceitasRespondeIds.OrderNecessaryIngredients),
                }));
            }
            else
            {
                await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.RecipeIngredientsNotFound);

                recipeState.CleanState();
                await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                await stepContext.CancelAllDialogsAsync();

                return(await stepContext.EndDialogAsync());
            }
        }
        private async Task <DialogTurnResult> NumberOfPersonForDinnerAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var recipeState = await UserProfileAccessor.GetAsync(stepContext.Context);

            if (recipeState.DoNotOrderFood.HasValue &&
                recipeState.DoNotOrderFood.Value)
            {
                return(await stepContext.NextAsync());
            }

            if (recipeState.UseRecipeOfTheWeek.HasValue && recipeState.UseRecipeOfTheWeek.Value)
            {
                // perguntar quantas pessoas o utilizador vai ter para jantar
                return(await stepContext.PromptAsync(DialogPromptIds.NumberOfPeopleForDinnerPrompt, new PromptOptions()
                {
                    Prompt = await _responder.RenderTemplate(
                        stepContext.Context,
                        stepContext.Context.Activity.Locale,
                        RecipeResponses.ReceitasRespondeIds.NumberOfPeopleForDinner),
                }));
            }
            else
            {
                // ler resposta se o utilizador quer encomendar pizza
                var resultOrderPizza = ParseSpokenBool(stepContext);

                if (resultOrderPizza.HasValue)
                {
                    if (resultOrderPizza.Value)
                    {
                        recipeState.OrderPizza = resultOrderPizza.Value;

                        recipeState.UseStoreRoomItems = true;

                        // criar carrinho de compras com a pizza
                        var pizza = new UStoreDBManagement(_context).GetIngredientPizza();
                        if (pizza != null)
                        {
                            Dictionary <int, int> necessaryIngredientsToBuy = new Dictionary <int, int>
                            {
                                { pizza.IngredientId, 1 },
                            }; // colocar no dicionário o ingrediente pizza

                            recipeState.OrderedIngredientsQuantities = necessaryIngredientsToBuy;
                            recipeState.TotalPrice = pizza.PricePerUnit;
                            recipeState.CartId     = new UStoreDBManagement(_context).CreateCart(necessaryIngredientsToBuy, pizza.PricePerUnit);
                        }
                        else
                        {
                            recipeState.CleanState();
                            await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                            throw new Exception("Não encontrou pizza na BD");
                        }

                        await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                        return(await stepContext.NextAsync());
                    }
                    else
                    {
                        recipeState.DoNotOrderFood = true;
                        await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                        return(await stepContext.NextAsync());
                    }
                }
            }

            return(await stepContext.NextAsync());

            //}
        }
        private async Task <DialogTurnResult> DisplayRecipeStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var recipeState = await UserProfileAccessor.GetAsync(stepContext.Context);

            if (recipeState.DoNotOrderFood.HasValue &&
                recipeState.DoNotOrderFood.Value)
            {
                return(await stepContext.NextAsync());
            }

            var lowerCaseNome = stepContext.Result as string;

            if (!string.IsNullOrWhiteSpace(lowerCaseNome) &&
                recipeState.UseRecipeOfTheWeek.HasValue &&
                recipeState.UseRecipeOfTheWeek.Value)
            {
                // recipeState.Name = lowerCaseNome;

                // convert string to int e ir buscar a opção da receita
                if (int.TryParse(lowerCaseNome, out int aux))
                {
                    var recipeSelected = recipeState.SugestedRecipes.ElementAt(aux - 1);

                    if (recipeSelected != null)
                    {
                        recipeState.RecipeId = recipeSelected.RecipeId;
                        recipeState.Name     = recipeSelected.Name;
                        await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);
                    }
                }
            }

            if (//!string.IsNullOrWhiteSpace(recipeState.Name) &&
                recipeState.RecipeId.HasValue &&
                recipeState.UseRecipeOfTheWeek.HasValue &&
                recipeState.UseRecipeOfTheWeek.Value)
            {
                // var ingredients = new UStoreDBManagement(_context).GetIngredientsFromRecipe(recipeState.Name);
                var ingredients = new UStoreDBManagement(_context).GetIngredientsFromRecipe(recipeState.RecipeId.Value);

                if (ingredients != null)
                {
                    await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.FollowingIngredientsInMind);

                    foreach (var ingredientLoop in ingredients)
                    {
                        await stepContext.Context.SendActivityAsync(ingredientLoop.Name, ingredientLoop.Name, InputHints.IgnoringInput);
                    }

                    return(await stepContext.NextAsync());
                }
                else
                {
                    await stepContext.Context.SendActivityAsync("I did not find that recipe.", "I did not find that recipe.", InputHints.IgnoringInput);

                    // return await stepContext.NextAsync();
                    recipeState.CleanState();
                    await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                    var evento = Activity.CreateEndOfConversationActivity();
                    await stepContext.Context.SendActivityAsync(evento);

                    return(await stepContext.EndDialogAsync());
                }
            }
            else
            {
                // o utilizador não quis a receita do mês e optou por inserir um ingrediente. perguntar se ele quer antes encomendar pizza
                return(await stepContext.PromptAsync(DialogPromptIds.AskUserOrderPizzaPrompt, new PromptOptions()
                {
                    Prompt = await _responder.RenderTemplate(
                        stepContext.Context,
                        stepContext.Context.Activity.Locale,
                        RecipeResponses.ReceitasRespondeIds.AskUserOrderPizza),
                }));
            }
        }
        private async Task <DialogTurnResult> UseRecipeOfTheWeek(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var recipeState = await UserProfileAccessor.GetAsync(stepContext.Context);

            if (recipeState.DoNotOrderFood.HasValue &&
                recipeState.DoNotOrderFood.Value)
            {
                return(await stepContext.NextAsync());
            }

            // var resultBlnUseRecipeOfTheWeek = stepContext.Result as bool?;
            var resultBlnUseRecipeOfTheWeek = ParseSpokenBool(stepContext);

            if (resultBlnUseRecipeOfTheWeek.HasValue)
            {
                recipeState.UseRecipeOfTheWeek = resultBlnUseRecipeOfTheWeek.Value;
                await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);
            }

            if (resultBlnUseRecipeOfTheWeek.HasValue && resultBlnUseRecipeOfTheWeek.Value)
            {
                // se ele aceitou a sugestão dar a hipotese de escolher a receita do mês mais duas
                //passar para lista de receitas sugeridas e pedir para ele escolher por opção

                var sugestedrecipes = new UStoreDBManagement(_context).GetSugestedRecipes();

                await _responder.ReplyWith(stepContext.Context, RecipeResponses.ReceitasRespondeIds.SugestedRecipes);

                if (sugestedrecipes != null && sugestedrecipes.Count > 0)
                {
                    // sugestedrecipes.ForEach(
                    //    async recipe => await stepContext.Context.SendActivityAsync("" + recipe.Name, recipe.Name, InputHints.IgnoringInput));

                    for (int i = 0; i < sugestedrecipes.Count; i++)
                    {
                        string strAux = string.Format("Option {0} - {1}", (i + 1).ToString(), sugestedrecipes[i].Name);
                        await stepContext.Context.SendActivityAsync(strAux, strAux, InputHints.IgnoringInput);
                    }

                    recipeState.SugestedRecipes = sugestedrecipes;
                    await UserProfileAccessor.SetAsync(stepContext.Context, recipeState);

                    return(await stepContext.PromptAsync(DialogPromptIds.SugestedRecipePrompt, new PromptOptions()
                    {
                        Prompt = await _responder.RenderTemplate(
                            stepContext.Context,
                            stepContext.Context.Activity.Locale,
                            RecipeResponses.ReceitasRespondeIds.WhichRecipePreferes),
                    }));
                }
                else
                {
                    throw new Exception("não encontrou receitas para apresentar");
                }
            }
            else
            {
                // pedir ao utilizador para escolher um ingrediente
                // rever fluxo
                return(await stepContext.PromptAsync(DialogPromptIds.AskForUserInputIngredient, new PromptOptions()
                {
                    Prompt = await _responder.RenderTemplate(
                        stepContext.Context,
                        stepContext.Context.Activity.Locale,
                        RecipeResponses.ReceitasRespondeIds.AskForUserInputIngredient),
                }));
            }
        }