public static Query CreateQueryFor(GetProductsByCategoryRequest request)
        {
            Query productQuery = new Query();
            Query colourQuery = new Query();
            Query brandQuery = new Query();
            Query sizeQuery = new Query();

            colourQuery.QueryOperator = QueryOperator.Or;
            foreach (int id in request.ColourIds)
                colourQuery.Add(Criterion.Create<Product>(p => p.Colour.Id, id, CriteriaOperator.Equal));

            if (colourQuery.Criteria.Count() > 0)
                productQuery.AddSubQuery(colourQuery);

            brandQuery.QueryOperator = QueryOperator.Or;
            foreach (int id in request.BrandIds)
                brandQuery.Add(Criterion.Create<Product>(p => p.Brand.Id, id, CriteriaOperator.Equal));

            if (brandQuery.Criteria.Count() > 0)
                productQuery.AddSubQuery(brandQuery);

            sizeQuery.QueryOperator = QueryOperator.Or;
            foreach (int id in request.SizeIds)
                sizeQuery.Add(Criterion.Create<Product>(p => p.Size.Id, id, CriteriaOperator.Equal));

            if (sizeQuery.Criteria.Count() > 0)
                productQuery.AddSubQuery(sizeQuery);

            productQuery.Add(Criterion.Create<Product>(p => p.Category.Id, request.CategoryId, CriteriaOperator.Equal));
            return productQuery;
        }
        private static GetProductsByCategoryRequest GenerateProductSearchRequestFrom(JsonProductSearchRequest jsonProductSearchRequest)
        {
            GetProductsByCategoryRequest productSearchRequest = new GetProductsByCategoryRequest();

            productSearchRequest.NumberOfResultsPerPage = ApplicationSettingsFactory.GetApplicationSettings().NumberOfResultsPerPage;
            productSearchRequest.Index = jsonProductSearchRequest.Index;
            productSearchRequest.CategoryId = jsonProductSearchRequest.CategoryId;
            productSearchRequest.SortBy = jsonProductSearchRequest.SortBy;

            List<RefinementGroup> refinementGroups = new List<RefinementGroup>();
            RefinementGroup refinementGroup;

            foreach (JsonRefinementGroup jsonRefinementGroup in jsonProductSearchRequest.RefinementGroups)
            {
                switch ((RefinementGroupings)jsonRefinementGroup.GroupId)
                {
                    case RefinementGroupings.brand:
                        productSearchRequest.BrandIds = jsonRefinementGroup.SelectedRefinements;
                        break;
                    case RefinementGroupings.colour:
                        productSearchRequest.ColourIds = jsonRefinementGroup.SelectedRefinements;
                        break;
                    case RefinementGroupings.size:
                        productSearchRequest.SizeIds = jsonRefinementGroup.SelectedRefinements;
                        break;
                    default:
                        break;
                }
            }
            return productSearchRequest;
        }
 private static GetProductsByCategoryRequest GenerateInitialProductSearchRequestFrom(int categoryId)
 {
     GetProductsByCategoryRequest productSearchRequest = new GetProductsByCategoryRequest();
     productSearchRequest.NumberOfResultsPerPage = ApplicationSettingsFactory.GetApplicationSettings().NumberOfResultsPerPage;
     productSearchRequest.CategoryId = categoryId;
     productSearchRequest.Index = 1;
     productSearchRequest.SortBy = ProductsSortBy.PriceHighToLow;
     return productSearchRequest;
 }
        public GetProductsByCategoryResponse GetProductsByCategory(GetProductsByCategoryRequest request)
        {
            GetProductsByCategoryResponse response;

            Query productQuery = ProductSearchRequestQueryGenerator.CreateQueryFor(request);

            IEnumerable<Product> productsMatchingRefinement = GetAllProductsMatchingQueryAndSort(request, productQuery);

            response = productsMatchingRefinement.CreateProductSearchResultFrom(request);

            response.SelectedCategoryName =
                _categoryRepository.FindBy(request.CategoryId).Name;

            return response;
        }
        public GetProductsByCategoryResponse GetProductsByCategory(GetProductsByCategoryRequest request)
        {
            GetProductsByCategoryResponse response;

            //ISpecification<Product> productSpec = ProductSearchRequestQueryGenerator.CreateSpecificationFor(request);

            var productsMatchingRefinement = GetAllProductsMatchingQuery(request);

            response = productsMatchingRefinement.CreateProductSearchResultFrom(request);

             var category = _presentationRepository.FindFirstByExample<CategoryDto>(new { Id = request.CategoryId });

            response.SelectedCategoryName = category.Name;

            return response;
        }
        public static GetProductsByCategoryResponse CreateProductSearchResultFrom(this IEnumerable<Product> productsMatchingRefinement, GetProductsByCategoryRequest request)
        {
            GetProductsByCategoryResponse productSearchResultView = new GetProductsByCategoryResponse();

            IEnumerable<ProductTitle> productsFound = productsMatchingRefinement.Select(p => p.Title).Distinct();

            productSearchResultView.SelectedCategory = request.CategoryId;

            productSearchResultView.NumberOfTitlesFound = productsFound.Count();

            productSearchResultView.TotalNumberOfPages = NoOfResultPagesGiven(request.NumberOfResultsPerPage,
                                                                              productSearchResultView.NumberOfTitlesFound);

            productSearchResultView.RefinementGroups = GenerateAvailableProductRefinementsFrom(productsFound);

            productSearchResultView.Products = CropProductListToSatisfyGivenIndex(request.Index, request.NumberOfResultsPerPage, productsFound);

            return productSearchResultView;
        }
        public static GetProductsByCategoryResponse CreateProductSearchResultFrom(this IEnumerable<ProductDto> productsMatchingRefinement, GetProductsByCategoryRequest request)
        {
            GetProductsByCategoryResponse productSearchResultView = new GetProductsByCategoryResponse();

            IEnumerable<ProductSummaryDto> typesOfProductsFound = productsMatchingRefinement.Select(e => new ProductSummaryDto() { Name = e.Name, BrandName = e.BrandName, Id = e.Id, Price = e.Price }).Distinct();

            productSearchResultView.SelectedCategory = request.CategoryId;

            productSearchResultView.NumberOfTitlesFound = typesOfProductsFound.Count();

            productSearchResultView.TotalNumberOfPages = NoOfResultPagesGiven(request.NumberOfResultsPerPage,
                                                                              productSearchResultView.NumberOfTitlesFound);

            productSearchResultView.RefinementGroups = GenerateAvailableProductRefinementsFrom(productsMatchingRefinement);

            productSearchResultView.Products = CropProductListToSatisfyGivenIndex(request.Index, request.NumberOfResultsPerPage, typesOfProductsFound);

            return productSearchResultView;
        }
        private IEnumerable<ProductDto> GetAllProductsMatchingQuery(GetProductsByCategoryRequest request)
        {
            var queryDtoSpec = new ProductDtoIsInCategorySpecification(request.CategoryId)
                    .And(new ProductDtoIsInColourSpecification(request.ColourIds))
                    .And(new ProductDtoIsMadeByBrandSpecification(request.BrandIds))
                    .And(new ProductDtoIsInSizeSpecification(request.SizeIds));

            IEnumerable<ProductDto> productsMatchingRefinement =
                _presentationRepository.FindBySpec<ProductDto>(queryDtoSpec);

            // TODO: Correct Sort By Logic)
            //switch (request.SortBy)
            //{
            //    case ProductsSortBy.PriceLowToHigh:
            //        productsMatchingRefinement = productsMatchingRefinement.OrderBy(p => p.Price);
            //        break;
            //    case ProductsSortBy.PriceHighToLow:
            //        productsMatchingRefinement = productsMatchingRefinement.OrderByDescending(p => p.Price);
            //        break;
            //}

            return productsMatchingRefinement;
        }
        public GetProductsByCategoryResponse GetProductsByCategory(GetProductsByCategoryRequest request)
        {
            var spec = new ProductDtoIsInCategorySpecification(request.CategoryId)
                    .And(new ProductDtoIsInColourSpecification(request.ColourIds))
                    .And(new ProductDtoIsMadeByBrandSpecification(request.BrandIds))
                    .And(new ProductDtoIsInSizeSpecification(request.SizeIds));

            IEnumerable<ProductDto> matchingProducts = FindAllProducts().Where(spec.IsSatisfiedBy);

            switch (request.SortBy)
            {
                case ProductsSortBy.PriceLowToHigh:
                    matchingProducts = matchingProducts.OrderBy(p => p.Price);
                    break;
                case ProductsSortBy.PriceHighToLow:
                    matchingProducts = matchingProducts.OrderByDescending(p => p.Price);
                    break;
            }

            GetProductsByCategoryResponse response = matchingProducts.CreateProductSearchResultFrom(request);

            response.SelectedCategoryName =
                GetAllCategories().Categories.Where(c => c.Id == request.CategoryId).FirstOrDefault().Name;

            return response;
        }
        private IEnumerable<Product> GetAllProductsMatchingQueryAndSort(GetProductsByCategoryRequest request, Query productQuery)
        {
            IEnumerable<Product> productsMatchingRefinement = _productRepository.FindBy(productQuery);

            switch (request.SortBy)
            {
                case ProductsSortBy.PriceLowToHigh:
                    productsMatchingRefinement = productsMatchingRefinement.OrderBy(p => p.Price);
                    break;
                case ProductsSortBy.PriceHighToLow:
                    productsMatchingRefinement = productsMatchingRefinement.OrderByDescending(p => p.Price);
                    break;
            }
            return productsMatchingRefinement;
        }