define(
    [
    'jquery',
    'ko',
    'underscore',
    'Magento_Checkout/js/model/quote',
    'Magento_Ui/js/modal/alert',
    'Magento_Checkout/js/model/totals',
    'Magento_Checkout/js/action/get-payment-information',
    'Magento_Checkout/js/action/recollect-shipping-rates',
    'mage/storage',
    'mage/translate',
    'Magento_Checkout/js/model/full-screen-loader',
    'Magento_SalesRule/js/model/payment/discount-messages',
    'Magento_Catalog/js/price-utils'
    ], function ($, ko, _, quote, alert, totals, getPaymentInformationAction, recollectShippingRates, storage, $t, fullScreenLoader, messageContainer, priceUtils) {
        'use strict';

        var dataModifiers = [],
        failCallbacks = [];

        return function (target) {
            return target.extend(
                {
                    availableOptions: ko.observableArray([]),

                    initialize: function () {
                        this._super(); //_super will call parent's `initialize` method here
                        self = this;
                    },

                    /**
                     * Check loyalty balance & display balance in dropdown
                     *
                     * @returns {String}
                     */
                    checkLoyaltyBalance: function () {
                        var self = this;
                        $.ajax(
                            {
                                showLoader: true,
                                url: 'loyaltydollar/loyaltybalancecheck',
                                type: 'POST',
                                success: function (data) {
                                    var objData = $.parseJSON(data);
                                    if (objData.status == "Error") {
                                        $("#loyaltyBalance").removeClass("message-success success message");
                                        $("#loyaltyBalance").addClass("message-error error message");
                                        $('#loyaltyBalance').html(objData.message);
                                        alert(
                                            {
                                                title: $.mage.__('Loyalty Dollar Tender Error'),
                                                content: $.mage.__(objData.message+', Please select another payment method.'),
                                                actions: {
                                                    always: function () { }
                                                }
                                            }
                                        );
                                    }
                                    if (objData.status == 'Approved') {
                                        $("#loyaltyBalance").removeClass("message-error error message");
                                        $("#loyaltyBalance").addClass("message-success success message");
                                        $('#loyaltyBalance').html(objData.message);
                                        var orderGrandTotal = parseFloat(objData.grandTotal);
                                        var availableLoyaltyBalance = parseFloat(objData.balance);
                                        if (availableLoyaltyBalance === 0) {
                                            $(".loyaltybalace.check.apply").css('display', 'none');
                                            $("#loyaltyBalance").removeClass("bloyal-error-message");
                                            $("#loyaltyBalance").addClass("message-success success message");
                                            $('#loyaltyBalance').html(objData.message);
                                            return;
                                        }
                                        $('#loyaltydollaramountvalue').val(availableLoyaltyBalance);
                                        var i;
                                        var apply_in_increments_of = (parseInt(window.checkoutConfig.apply_in_increments_of) != 0) ? parseInt(window.checkoutConfig.apply_in_increments_of) : 10;
                                        var apply_full_balance = parseInt(window.checkoutConfig.apply_full_balance);
                                        if(apply_full_balance == 0) {
                                            self.availableOptions.removeAll();
                                            if (orderGrandTotal > availableLoyaltyBalance) {
                                                var dropDownNumbers = availableLoyaltyBalance / apply_in_increments_of;
                                                for (i = 1; i <= dropDownNumbers; i++) {
                                                    var option = {
                                                        'value': i * apply_in_increments_of,
                                                        'label': priceUtils.formatPrice(i * apply_in_increments_of)
                                                    }
                                                    self.availableOptions.push(option);
                                                }
                                                $(".loyaltybalace.check.apply").css('display', 'block');
                                                $("#loyaltyRedeemBalance").prop('disabled', false);
                                            } else if (availableLoyaltyBalance > orderGrandTotal) {
                                                var applicableBalance = orderGrandTotal;
                                                var dropDownNumbers = applicableBalance / apply_in_increments_of;
                                                for (i = 1; i <= dropDownNumbers; i++) {
                                                    var option = {
                                                        'value': i * apply_in_increments_of,
                                                        'label': priceUtils.formatPrice(i * apply_in_increments_of)
                                                    }
                                                    self.availableOptions.push(option);
                                                }
                                                $(".loyaltybalace.check.apply").css('display', 'block');
                                                $("#loyaltyRedeemBalance").prop('disabled', false);
                                            } else if (orderGrandTotal == availableLoyaltyBalance) {
                                                var dropDownNumbers = orderGrandTotal / apply_in_increments_of;
                                                for (i = 1; i <= dropDownNumbers; i++) {
                                                    var option = {
                                                        'value': i * apply_in_increments_of,
                                                        'label': priceUtils.formatPrice(i * apply_in_increments_of)
                                                    }
                                                    self.availableOptions.push(option);
                                                }
                                                $(".loyaltybalace.check.apply").css('display', 'block');
                                                $("#loyaltyRedeemBalance").prop('disabled', false);
                                            }

                                        } else {

                                            if (availableLoyaltyBalance == orderGrandTotal) {
                                                $("#loyaltyDollarAmount").val(availableLoyaltyBalance);
                                            }
                                            if (availableLoyaltyBalance > orderGrandTotal) {
                                                $("#loyaltyDollarAmount").val(orderGrandTotal);
                                            }
                                            if (orderGrandTotal > availableLoyaltyBalance) {
                                                $("#loyaltyDollarAmount").val(availableLoyaltyBalance);
                                            }
                                            $("#loyaltyRedeemBalance").prop('disabled', false);
                                        }
                                    }
                                }
                            }
                        );
                    },

                    /**
                     * @param  {int} quoteId
                     * @param  {float} applyAmount
                     * @return {*}
                     */
                    getRedeemLoyaltyBalanceUrl: function (quoteId, applyAmount) {
                        return 'checkout/loyaltydollar/loyaltybalanceredeem/quoteId/'
                        + encodeURIComponent(quoteId);
                    },

                    /**
                     * Redeem Loyalty balance
                     *
                     * @returns {String}
                     */
                    redeemLoyaltyBalance: function () {
                        var applyAmount = $('#loyaltyDollarAmount').val(),
                        orderGrandTotoal = parseFloat(totals.totals()['grand_total']),
                        availableloyaltyDollarBalance = parseFloat($('#loyaltydollaramountvalue').val()),
                        url = self.getRedeemLoyaltyBalanceUrl(quote.getQuoteId(), $('#loyaltyDollarAmount').val()),
                        message = $t('Loyalty dollar successfully applied.'),
                        data = {'applyAmount': applyAmount},
                        headers = {};
                        if (applyAmount == "" ||  applyAmount == '0' || applyAmount < '0') {
                            $("#loyaltyBalanceRedeem").addClass("bloyal-error-message");
                            $('#loyaltyBalanceRedeem').html("Please click on check balance");
                            return;
                        }
                        applyAmount = parseFloat(applyAmount);
                        if (applyAmount > availableloyaltyDollarBalance) {
                            $("#loyaltyBalanceRedeem").addClass("bloyal-error-message");
                            $('#loyaltyBalanceRedeem').html("You can not apply more than available balance");
                            return;
                        }
                        if (applyAmount > orderGrandTotoal) {
                            $("#loyaltyBalanceRedeem").addClass("bloyal-error-message");
                            $('#loyaltyBalanceRedeem').html("Applied amount can't be greater than order total!");
                            return;
                        }
                        $('#loyaltyBalanceRedeem').html("");
                        //Allowing to modify coupon-apply request
                        dataModifiers.forEach(
                            function (modifier) {
                                modifier(headers, data);
                            }
                        );
                        fullScreenLoader.startLoader();
                        storage.post(
                            url,
                            data,
                            false,
                            null,
                            headers
                        ).done(
                            function (response) {
                                var deferred;
                                if (response) {
                                    deferred = $.Deferred();
                                    totals.isLoading(true);
                                    recollectShippingRates();
                                    getPaymentInformationAction(deferred);
                                    $.when(deferred).done(
                                        function () {
                                            fullScreenLoader.stopLoader();
                                            totals.isLoading(false);
                                            var grandTotal = parseFloat(totals.totals()['grand_total']);
                                            if (grandTotal > 0) {
                                                alert(
                                                    {
                                                        title: $.mage.__('Loyalty Dollar Tender'),
                                                        content: $.mage.__('Loyalty voucher funds have been applied. You will need an additional mode of payment to cover the remaining cost.'),
                                                        actions: {
                                                            always: function () { }
                                                        }
                                                    }
                                                );
                                            }
                            
                                        }
                                    );
                                    messageContainer.addSuccessMessage(
                                        {
                                            'message': message
                                        }
                                    );
                                }
                            }
                        ).fail(
                            function (response) {
                                totals.isLoading(false);
                                errorProcessor.process(response, messageContainer);
                                //Allowing to tap into apply-coupon process.
                                failCallbacks.forEach(
                                    function (callback) {
                                        callback(response);
                                    }
                                );
                            }
                        );
                    }
                }
            );
        }
    }
);