public async Task <IActionResult> CreateMenu(String RestaurantName, [Bind("Name,MenuType,Visibility,Hours")] Menu entity)
        {
            var checkIfExists = from getRestaurant in RestaurantDomain.GetRestaurant(RestaurantName)
                                let restaurant = (getRestaurant as RestaurantSelected)?.RestaurantAgg.Restaurant
                                                 from getMenu in RestaurantDomain.GetMenu(entity.Name, restaurant.Id)
                                                 select getMenu;
            var checkIfExistsResult = await interpreter.Interpret(checkIfExists, Unit.Default);

            return(await checkIfExistsResult.MatchAsync <IActionResult>(
                       async exists =>
            {
                return BadRequest();
            },
                       async inexistent =>
            {
                var expr = from getRestaurant in RestaurantDomain.GetRestaurant(RestaurantName)
                           let restaurant = (getRestaurant as RestaurantSelected)?.RestaurantAgg.Restaurant
                                            from createEntity in RestaurantDomain.CreateAndPersistMenu(entity, restaurant)
                                            let entityC = (createEntity as MenuCreated)?.Menu
                                                          select createEntity;

                var result = await interpreter.Interpret(expr, Unit.Default);
                return await result.MatchAsync <IActionResult>(
                    async(created) =>
                {
                    //await interpreter.Interpret(Database.AddOrUpdateEntity(created.Menu.Menu), Unit.Default);
                    return (IActionResult)Ok(created.Menu.Menu);
                },
                    async(notCreated) =>
                {
                    return BadRequest();
                });
            }
                       ));
        }
        public async Task <IActionResult> GetAllMenuItems(String restaurantName, String menuName)
        {
            var getAllMenuItemsExpr = from selectRestaurant in RestaurantDomain.GetRestaurant(restaurantName)
                                      let restaurant = (selectRestaurant as RestaurantSelected)?.RestaurantAgg
                                                       from selectMenu in RestaurantDomain.GetMenu(menuName, restaurant.Restaurant.Id)
                                                       let menu = (selectMenu as MenuSelected)?.MenuAgg
                                                                  from getAllMenus in RestaurantDomain.GetAllMenuItems(menu.Menu.Id)
                                                                  select getAllMenus;

            return(Ok(await interpreter.Interpret(getAllMenuItemsExpr, Unit.Default)));
        }
        public async Task <IActionResult> GetMenuItems(int menuId)
        {
            var getMenuExpr =
                from menuResult in RestaurantDomain.GetMenu(menuId)
                select menuResult;
            var menu = await _interpreter.Interpret(getMenuExpr, Unit.Default);

            var getMenu =
                from menuResult in RestaurantDomainEx.GetMenu(menuId)
                select menuResult;
            var menuAgg = await _interpreter.Interpret(getMenu, Unit.Default);

            var getMenuItemsExpr =
                from menuItemsResult in RestaurantDomainEx.GetMenuItems(menuAgg.Menu)
                select menuItemsResult;
            var menuItems = await _interpreter.Interpret(getMenuItemsExpr, Unit.Default);

            return(menu.Match(
                       found => (IActionResult)Ok(found.Agg.Menu.MenuItems),
                       notFound => NotFound()));
        }
        public async Task <IActionResult> CreateMenuItem(String RestaurantName, String MenuName, [Bind("Name,Ingredients,Alergens,Price,Image")] MenuItem entity)
        {
            var checkIfExistsExpr = from selectRestaurant in RestaurantDomain.GetRestaurant(RestaurantName)
                                    let restaurant = (selectRestaurant as RestaurantSelected)?.RestaurantAgg.Restaurant
                                                     from selectMenu in RestaurantDomain.GetMenu(MenuName, restaurant.Id)
                                                     let menu = (selectMenu as MenuSelected)?.MenuAgg.Menu
                                                                from selectMenuItem in RestaurantDomain.GetMenuItem(entity.Name, menu.Id)
                                                                select selectMenuItem;

            var checkIfExistsResult = await interpreter.Interpret(checkIfExistsExpr, Unit.Default);

            return(await checkIfExistsResult.MatchAsync <IActionResult>(
                       async exists =>
            {
                return BadRequest();
            },
                       async inexistent =>
            {
                var expr = from selectRestaurant in RestaurantDomain.GetRestaurant(RestaurantName)
                           let restaurant = (selectRestaurant as RestaurantSelected)?.RestaurantAgg.Restaurant
                                            from selectMenu in RestaurantDomain.GetMenu(MenuName, restaurant.Id)
                                            let menu = (selectMenu as MenuSelected)?.MenuAgg.Menu
                                                       from createEntity in RestaurantDomain.CreateAndPersistMenuItem(menu, entity)
                                                       let entityC = (createEntity as MenuItemCreated)?.MenuItemAgg
                                                                     select createEntity;

                var result = await interpreter.Interpret(expr, Unit.Default);
                return await result.MatchAsync <IActionResult>(
                    async(created) =>
                {
                    await interpreter.Interpret(Database.AddOrUpdateEntity(created.MenuItemAgg.MenuItem), Unit.Default);
                    return (IActionResult)Ok(created.MenuItemAgg.MenuItem);
                },
                    async(notCreated) =>
                {
                    return BadRequest();
                });
            }
                       ));
        }
        public async Task <IActionResult> GetMenuItem(String restaurantName, String menuName, String menuItemName)
        {
            var getMenuItemExpr = from restaurantResult in RestaurantDomain.GetRestaurant(restaurantName)
                                  let restaurant = (restaurantResult as RestaurantSelected)?.RestaurantAgg.Restaurant
                                                   from menuResult in RestaurantDomain.GetMenu(menuName, restaurant.Id)
                                                   let menu = (menuResult as MenuSelected)?.MenuAgg.Menu
                                                              from menuItemResult in RestaurantDomain.GetMenuItem(menuItemName, menu.Id)

                                                              select menuItemResult;

            var getMenuItemResult = await interpreter.Interpret(getMenuItemExpr, Unit.Default);

            return(await getMenuItemResult.MatchAsync <IActionResult>(
                       async (selected) =>
            {
                return (IActionResult)Ok(JsonConvert.SerializeObject(selected.MenuItemAgg.MenuItem));
            },
                       async (notSelected) =>
            {
                return NotFound();
            }
                       ));
        }
        public async Task <IActionResult> GetMenu(string restaurantName, String menuName)
        {
            //Selecting the restaurant
            var expr = from selectRestaurant in RestaurantDomain.GetRestaurant(restaurantName)
                       let restaurant = (selectRestaurant as RestaurantSelected)?.RestaurantAgg
                                        from selectMenu in RestaurantDomain.GetMenu(menuName, restaurant.Restaurant.Id)
                                        let menu = (selectMenu as MenuSelected)?.MenuAgg
                                                   select selectMenu;

            var exprResult = await interpreter.Interpret(expr, Unit.Default);

            return(await exprResult.MatchAsync <IActionResult>(
                       async (selected) =>  // Menu was successfully selected
            {
                return (IActionResult)Ok(selected.MenuAgg.Menu);
            },
                       async (notSelected) =>  // Menu not selected
            {
                return NotFound();
            }

                       ));
        }
        public static async Task Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddOperations(typeof(RestaurantAgg).Assembly);
            serviceCollection.AddOperations(typeof(MenuAgg).Assembly);
            serviceCollection.AddOperations(typeof(AddOrUpdateEntityOp).Assembly);
            serviceCollection.AddTransient(typeof(IOp <,>), typeof(QueryOp <,>));

            serviceCollection.AddDbContext <OrderAndPayContext>(ServiceLifetime.Singleton);

            var serviceProvider = serviceCollection.BuildServiceProvider();

            var interpreter = new LiveInterpreterAsync(serviceProvider);

            //Selecting the restaurant
            var expr = from selectRestaurant in RestaurantDomain.GetRestaurant("McDonalds")
                       let restaurant = (selectRestaurant as RestaurantAgg)?.Restaurant
                                        select selectRestaurant;

            var exprResult = await interpreter.Interpret(expr, Unit.Default);

            var finalExpr = await exprResult.MatchAsync(
                async (persisted) => // Restaurant Successfully selected
            {
                // Populates the RestaurantAgg model with the data from two functions, using a LiveAsyncInterpreter.
                // This function will firstly populate the ICollection<Menu> Menus by calling GetAllMenus, with all the menus from the database that have the restaurant's id
                // After the ICollection<Menu> will be filled, for each entity it will call the GetAllMenuItems function to populate the menu
                await RestaurantDomain.PopulateRestaurantModel(persisted.RestaurantAgg, RestaurantDomain.GetAllMenus, RestaurantDomain.GetAllMenuItems, interpreter);

                //// Selects a menu with a specific name
                var selectMenuExpr                       = from selectMenu in RestaurantDomain.GetMenu("Chicken", persisted.RestaurantAgg.Restaurant.Id)
                                                let menu = (selectMenu as MenuSelected)?.MenuAgg
                                                           select selectMenu;

                var selectMenuRes    = await interpreter.Interpret(selectMenuExpr, Unit.Default);
                var selectMenuResult = await selectMenuRes.MatchAsync(
                    async(selected) =>      // Menu was successfully selected
                {
                    selected.MenuAgg.Menu.Hours = "8-13";

                    var updateRestaurantExprUnique = from updateRestauruant in RestaurantDomain.UpdateAndPersistMenu(selected.MenuAgg.Menu)
                                                     let updatem = (updateRestauruant as MenuUpdated)?.Menu
                                                                   select updateRestauruant;
                    var updateRestaurantFin = await interpreter.Interpret(updateRestaurantExprUnique, Unit.Default);

                    var matchh = updateRestaurantFin.Match(
                        updated =>
                    {
                        return(updated);
                    },
                        notUpdated =>
                    {
                        return(notUpdated);
                    }
                        );
                    //var getAllMenuItems = from getAllMenus in RestaurantDomain.GetAllMenuItems(10)
                    //                      select getAllMenus;

                    //var getAllMenusResult = await interpreter.Interpret(getAllMenuItems, Unit.Default);

                    return(selected);
                },
                    async(notSelected) =>      // Menu not selected
                {
                    return(notSelected);
                }

                    );

                return(persisted);
            },
                async (notPersisted) => // Restaurant not selected
            {
                return(notPersisted);
            }

                );

            Console.WriteLine("Hello World!");
        }