class CheckoutServiceFacadeImpl implements CheckoutServiceFacade {

    @Override
    public PriceModel getOrderDeliveryTotalShipping(final CustomerOrder customerOrder, final CustomerOrderDelivery delivery, final ShoppingCart cart) {

        final Total grandTotal = getOrderDeliveryTotal(customerOrder, delivery);

        boolean hasTax = MoneyUtils.isPositive(grandTotal.getDeliveryTax());
        final boolean showTax = hasTax && cart.getShoppingContext().isTaxInfoEnabled();
        final boolean showTaxNet = showTax && cart.getShoppingContext().isTaxInfoUseNet();
        final boolean showTaxAmount = showTax && cart.getShoppingContext().isTaxInfoShowAmount();

        final boolean hasDiscount = MoneyUtils.isFirstBiggerThanSecond(grandTotal.getDeliveryListCost(), grandTotal.getDeliveryCost());

        if (showTax) {

            final String firstTaxCode = delivery.getTaxCode();

            final BigDecimal netAmount = grandTotal.getDeliveryCostAmount().subtract(grandTotal.getDeliveryTax());
            final BigDecimal taxPercent = grandTotal.getDeliveryTax().divide(netAmount, Constants.TAX_SCALE, BigDecimal.ROUND_FLOOR);
            final BigDecimal taxRate = taxPercent.multiply(MoneyUtils.HUNDRED).setScale(Constants.MONEY_SCALE, BigDecimal.ROUND_HALF_UP);

            final boolean priceTaxExclusive = MoneyUtils.isFirstBiggerThanSecond(grandTotal.getDeliveryCostAmount(), grandTotal.getDeliveryCost());

            if (hasDiscount) {

                return new PriceModelImpl(DELIVERY_SHIPPING_REF, customerOrder.getCurrency(), BigDecimal.ONE,
                        false,
                        false,
                        showTaxNet ?
                                MoneyUtils.getNetAmount(grandTotal.getDeliveryListCost(), taxRate, !priceTaxExclusive) :
                                MoneyUtils.getGrossAmount(grandTotal.getDeliveryListCost(), taxRate, !priceTaxExclusive),
                        showTaxNet ?
                                grandTotal.getDeliveryCostAmount().subtract(grandTotal.getDeliveryTax()) :
                                grandTotal.getDeliveryCostAmount(),
                        showTax, showTaxNet, showTaxAmount,
                        firstTaxCode,
                        taxRate,
                        priceTaxExclusive,
                        grandTotal.getDeliveryTax()
                );

            }


            return new PriceModelImpl(DELIVERY_SHIPPING_REF, customerOrder.getCurrency(), BigDecimal.ONE,
                    false,
                    false,
                    showTaxNet ?
                            grandTotal.getDeliveryCostAmount().subtract(grandTotal.getDeliveryTax()) :
                            grandTotal.getDeliveryCostAmount(),
                    null,
                    showTax, showTaxNet, showTaxAmount,
                    firstTaxCode,
                    taxRate,
                    priceTaxExclusive,
                    grandTotal.getDeliveryTax()
            );

        }

        if (hasDiscount) {

            return new PriceModelImpl(
                    DELIVERY_SHIPPING_REF,
                    customerOrder.getCurrency(),
                    BigDecimal.ONE,
                    false,
                    false,
                    grandTotal.getDeliveryListCost(),
                    grandTotal.getDeliveryCost()
            );

        }

        return new PriceModelImpl(
                DELIVERY_SHIPPING_REF,
                customerOrder.getCurrency(),
                BigDecimal.ONE,
                false,
                false,
                grandTotal.getDeliveryCost(),
                null
        );

    }

    public  CheckoutServiceFacadeImpl(final CustomerOrderService customerOrderService,
                                     final AmountCalculationStrategy amountCalculationStrategy,
                                     final DeliveryTimeEstimationVisitor deliveryTimeEstimationVisitor,
                                     final CustomerOrderPaymentService customerOrderPaymentService,
                                     final CarrierSlaService carrierSlaService,
                                     final PaymentProcessorFactory paymentProcessorFactory,
                                     final PaymentModulesManager paymentModulesManager,
                                     final ReportGenerator reportGenerator);

}