class ProductServiceFacadeImpl implements ProductServiceFacade {

    @Override
    public Pair<PriceModel, CustomerWishList.PriceChange> getSkuPrice(final ShoppingCart cart,
                                                                      final CustomerWishList item) {

        if (cart.getShoppingContext().isHidePrices()) {
            return new Pair<>(
                    getNullProductPriceModel(cart.getCurrencyCode()),
                    new CustomerWishList.PriceChange(CustomerWishList.PriceChangeType.NOCHANGE, null)
            );
        }

        final String sku = item.getSkuCode();
        final String supplier = item.getSupplierCode();
        final BigDecimal qty = item.getQuantity();

        final SkuPrice priceNow = resolveMinimalPrice(cart, null, sku, qty, supplier);

        final String addedPriceCurr = item.getRegularPriceCurrencyWhenAdded();
        final Pair<BigDecimal, BigDecimal> price;
        final CustomerWishList.PriceChange priceInfo;
        if (isPriceValid(priceNow)) {
            if (cart.getCurrencyCode().equals(addedPriceCurr)) {
                final BigDecimal addedPrice = item.getRegularPriceWhenAdded();
                final Pair<BigDecimal, BigDecimal> listAndSale = priceNow.getSalePriceForCalculation();
                final BigDecimal saleNow = MoneyUtils.secondOrFirst(listAndSale);
                if (MoneyUtils.isFirstEqualToSecond(addedPrice, saleNow)) {
                    // no change
                    if (MoneyUtils.isFirstBiggerThanSecond(listAndSale.getFirst(), addedPrice)) {
                        price = new Pair<>(listAndSale.getFirst(), addedPrice);
                        priceInfo = new CustomerWishList.PriceChange(
                                CustomerWishList.PriceChangeType.ONSALE,
                                MoneyUtils.getDiscountDisplayValue(listAndSale.getFirst(), addedPrice)
                        );
                    } else {
                        // not on sale
                        price = new Pair<>(addedPrice, null);
                        priceInfo = new CustomerWishList.PriceChange(CustomerWishList.PriceChangeType.NOCHANGE, null);
                    }
                } else if (MoneyUtils.isFirstBiggerThanSecond(addedPrice, saleNow)) {
                    // price dropped since added
                    price = new Pair<>(addedPrice, saleNow);
                    priceInfo = new CustomerWishList.PriceChange(
                            CustomerWishList.PriceChangeType.DECREASED,
                            MoneyUtils.getDiscountDisplayValue(addedPrice, saleNow)
                    );
                } else if (MoneyUtils.isPositive(addedPrice)) {
                    // price gone up
                    price = listAndSale;
                    priceInfo = new CustomerWishList.PriceChange(
                            CustomerWishList.PriceChangeType.INCRSEASED,
                            MoneyUtils.getDiscountDisplayValue(addedPrice, saleNow).negate()
                    );
                } else {
                    // invalid config - old price is zero or negative
                    price = listAndSale;
                    priceInfo = new CustomerWishList.PriceChange(CustomerWishList.PriceChangeType.NOCHANGE, null);
                }
            } else {
                // no comparative price - different currency
                price = priceNow.getSalePriceForCalculation();
                priceInfo = new CustomerWishList.PriceChange(CustomerWishList.PriceChangeType.DIFFCURRENCY, null);
            }
        } else {
            // Item is not priced now so it cannot be bought
            price = new Pair<>(null, null);
            priceInfo = new CustomerWishList.PriceChange(CustomerWishList.PriceChangeType.OFFLINE, null);
        }

        final PriceModel model = getSkuPrice(
                cart,
                sku,
                BigDecimal.ONE,
                priceNow.isPriceUponRequest(),
                priceNow.isPriceOnOffer(),
                price.getFirst(),
                price.getSecond(),
                supplier
        );

        return new Pair<>(model, priceInfo);

    }

    public  ProductServiceFacadeImpl(final ProductService productService,
                                    final ProductSkuService productSkuService,
                                    final ProductAssociationService productAssociationService,
                                    final SearchQueryFactory searchQueryFactory,
                                    final ProductAvailabilityStrategy productAvailabilityStrategy,
                                    final ProductQuantityStrategy productQuantityStrategy,
                                    final PricingPolicyProvider pricingPolicyProvider,
                                    final PriceResolver priceResolver,
                                    final ShoppingCartCalculator shoppingCartCalculator,
                                    final PromotionService promotionService,
                                    final CategoryServiceFacade categoryServiceFacade,
                                    final ShopService shopService,
                                    final BrandService brandService);

}