// https://docs.djangoproject.com/en/3.2/ref/csrf/#ajax
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

$(function() {
    // show billing address box if checkbox is selected.
    handleBillingAddressSelect(
        $('#id_select_billing_address_form-require_billing_address')
    ).change(function(e) {
        handleBillingAddressSelect(e.target);
    });

    // store values of form inputs here to check for changes when triggered by focusout
    var hash = {
        line1: null,
        country: null,
        shipping_method_code: null,
        payment_method: null,
    };

    getOrderTotal(hash)
    // attach change handler to the only 2 required form fields (according to oscarapi)
    $('#id_shipping_address_form-line1').focusout(function() {
        getShippingMethods(hash);
    });
    $('#id_shipping_address_form-country').change(function() {
        getShippingMethods(hash);
        getPaymentMethods();
    });
    $('#id_billing_address_form-country').change(function() {
        getPaymentMethods();
        getOrderTotal(hash);
    });
    $(document).on('change', 'input[name="shipping_method_form-method_code"], input[name="payment_method_form-payment_method"]', function() {
        getOrderTotal(hash);
    });
    $('#id_shipping_address_chooser-address_chooser').change(function() {
        updateAddress($("#id_shipping_address_chooser-address_chooser").val(), "shipping")
    });
    $('#id_billing_address_chooser-address_chooser').change(function () {
        updateAddress($("#id_billing_address_chooser-address_chooser").val(), "billing")
    });
    // attach change handler to the gatway options radiogroup.
    $("#gateway > div.panel-body input[name='gateway_form-options'],#gateway > div.card-body input[name='gateway_form-options']").change(function(e) {
        var chosenOption = $(e.target).val();
        handleGatewayOptionChosen(chosenOption);
    });
    handleGatewayOptionChosen($("#gateway > div.panel-body input[name='gateway_form-options']:checked,#gateway > div.card-body input[name='gateway_form-options']:checked").val());
    getOrderTotal(hash)

    $("#voucher_form").submit(function(event) {
        handleVoucherFormSubmit(event);
    });
    $("#voucher_form button[type='submit']").click(function(event) {
        handleVoucherFormSubmit(event);
    });
});

/**
 * Shows and hides the billing address form block depending if the checkbox
 * is checked or not checked.
 */

function handleBillingAddressSelect(checkbox) {
    if($(checkbox).is(':checked')) {
        $("#billing-address-form-block").show();
    } else {
        $("#billing-address-form-block").hide();
    }
    return checkbox;
}

/**
 * Shows and hides some form fields depending on the registration options
 * that have been seleected.
 */

function handleGatewayOptionChosen(chosenOption) {
    if (chosenOption == "existing") {
        $("#gateway > div.panel-body > #passwords,#gateway > div.card-body > #passwords").css('max-height', '150px');
        $("#gateway > div.panel-body > #passwords > .form-group:last-of-type,#gateway > div.card-body > #passwords > .form-group:last-of-type").hide();
        $("#loginbutton").show();
    } else if (chosenOption == "new") {
        $("#gateway > div.panel-body > #passwords > .form-group:last-of-type,#gateway > div.card-body > #passwords > .form-group:last-of-type").show();
        $("#gateway > div.panel-body > #passwords,#gateway > div.card-body > #passwords").css('max-height', '180px');
        $("#loginbutton").hide();
    } else {
        $("#gateway > div.panel-body > #passwords > .form-group:last-child(),#gateway > div.card-body > #passwords > .form-group:last-child()").show();
        $("#gateway > div.panel-body > #passwords,#gateway > div.card-body > #passwords").css('max-height', 0);
        $("#loginbutton").hide();
    }
}

/*
 * Returns the api call with the correct language parameter in front (if any)
 */

function getLocalizedURL(url) {
    try {
      var i18nPathBase = window.location.pathname.split('/checkout/')[0];
      return i18nPathBase.concat(url);
    } catch (e) {
      return url;
    }
}


/**
* hackTogetherFullCountryUrl creates the api location from the country id.
*/

function hackTogetherFullCountryUrl(countryId) {
    return [document.location.origin, getLocalizedURL("/checkout/api/countries/"), countryId, "/"].join("");
}

/**
* getCountryFromFullCountryUrl gets the country code / id from a full country URL.
*/

function getCountryFromFullCountryUrl(countryURL) {
    return countryURL.replace(document.location.origin + getLocalizedURL("/checkout/api/countries/"), "").replace("/", "");
}

/**
* Get all the form data from the html prefixed with the param.
*/

function getFormData(prefix) {
    var result = {};
    var prefixLength = prefix.length + 1;
    $('form#onstepcheckout').find("[name^=" + prefix + "]").each(function(index, formInput) {
        var value = $(formInput).val();
        if (value !== null && value !== undefined && value !== "") {
            result[formInput.name.substring(prefixLength)] = value;
        }
    });
    return result;
}


/**
* postOrderTotal does the actual request to the backend API based on the
* selectedShippingMethod and selectedPaymentMethod. See also
* the getOrderTotal function
*/
function postOrderTotal(selectedShippingMethod, selectedPaymentMethod) {
    var form = $('form#onstepcheckout');
    var shippingAddress = getFormData('shipping_address_form');
    var gatewayData = getFormData('gateway_form');

    shippingAddress.country = hackTogetherFullCountryUrl(shippingAddress.country);
    shippingAddress.line1 = shippingAddress.line1 ? shippingAddress.line1 : "placeholder";

    var formData = {
        shipping_address: shippingAddress,
        shipping_method_code: selectedShippingMethod,
        payment_method: selectedPaymentMethod,
        guest_email: gatewayData.username
    };

    if(window.getOrderTotalRequest){
        window.getOrderTotalRequest.abort();
    }

    window.getOrderTotalRequest = $.ajax({
        url: getLocalizedURL('/checkout/api/basket/total/'),
        type: 'post',
        data: JSON.stringify(formData),
        headers: {
            "X-CSRFToken": getCookie('csrftoken'),
        },
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        success: function (data) {
            $("#checkouttotal").replaceWith($(data.snippet));
            window.getOrderTotalRequest = null;
        }
    });
}


/**
 * getOrderTotal retries the order total from the backend after selecting a
 * shipping method.
 */

function getOrderTotal(hash) {
    var selectedShippingMethod = $('form#onstepcheckout').find("input:radio[name ='shipping_method_form-method_code']:checked").val();
    var selectedPaymentMethod = $('form#onstepcheckout').find("input:radio[name ='payment_method_form-payment_method']:checked").val();
    if (hash.shipping_method_code != selectedShippingMethod || hash.payment_method != selectedPaymentMethod) {
        hash.shipping_method_code = selectedShippingMethod;
        hash.payment_method = selectedPaymentMethod;
        postOrderTotal(selectedShippingMethod, selectedPaymentMethod);
   }
}

/**
* getShippingMethods fetches the shippingmethods from the server,
* after entering a enough of the shipping address to determine prices.
* the prices can depend on the location of the customer.
*/

function getShippingMethods(hash) {
    var formData = getFormData('shipping_address_form');
    
    if ((hash.country != formData.country || hash.line1 != formData.line1)) {
        hash.country = formData.country;
        hash.line1 = formData.line1;

        formData.country = hackTogetherFullCountryUrl(formData.country);

        if(window.getShippingMethodsRequest){
            window.getShippingMethodsRequest.abort();
        }

        window.getShippingMethodsRequest = $.ajax({
            url: getLocalizedURL('/checkout/api/basket/shipping-methods.html'),
            type: 'post',
            data: JSON.stringify(formData),
            headers: {
                "X-CSRFToken": getCookie('csrftoken'),
            },
            contentType: 'application/json; charset=utf-8',
            dataType: 'html',
            success: function (data) {
                $("#shipping_method_form").replaceWith(data);
                window.getShippingMethodsRequest = null;
                getOrderTotal(hash);
            }
        });
    }
}

function getPaymentMethods() {
    // Clear current selected payment method, otherwise it might show outdated
    // payment method info in the checkout total block.
    $('input[name="payment_method_form-payment_method"').prop('checked', false);

    if ($('#billing-address-form-block').is(":visible"))
        var formData = getFormData('billing_address_form');
    else
        var formData = getFormData('shipping_address_form');

    if(window.getPaymentMethodsRequest){
        window.getPaymentMethodsRequest.abort();
    }

    window.getPaymentMethodsRequest = $.ajax({
        url: getLocalizedURL('/checkout/api/basket/payment-methods/'),
        type: 'post',
        data: JSON.stringify(formData),
        headers: {
            "X-CSRFToken": getCookie('csrftoken'),
        },
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        success: function (data) {
            $('#payment_method_form').replaceWith(data.snippet);
            window.getPaymentMethodsRequest = null;
        }
    })
}

function updateAddress(address_id, type) {
    $.ajax({
        url: getLocalizedURL('/checkout/api/useraddresses/' + address_id + '/'),
        type: 'get',
        headers: {
            "X-CSRFToken": getCookie('csrftoken'),
        },
        success: function(data) {
            var triggers = [];
            delete data["notes"]
            for (var key in data) {
                if(key == "country"){
                    data[key] = getCountryFromFullCountryUrl(data[key]);
                }

                var field = $("#id_" + type + "_address_form-" + key);
                if(field.length && field.val() != data[key]){
                    field.val(data[key]);
                    triggers.push(field);
                }
            }

            $(triggers).each(function(){
                $(this).trigger('change');
            });
        }
    });
}

function handleVoucherFormSubmit(event) {
    /*
        When a voucher is submitted from the checkout and you have already entered some other form data,
        it would get lost due to the page reload. To fix this, we could store the current formdata
        in localstorage and then on certain conditions re-fill the forms with this data.

        However, we can post to the add voucher view just fine which will return html to us.
        And we can use this HTML to show messages and reload the order total with getOrderTotal();

        This is also how oscar does it too in the basket view with deletion or update of quantity.
    */

    // Don't submit the form, we'll handle it with AJAX to prevent data loss.
    event.preventDefault();

    var voucherCodeElem = $('#voucher_form input#id_code');

    $.post({
        url: getLocalizedURL('/basket/vouchers/add/'),
        data: "code=" + $(voucherCodeElem).val(),
        headers: {
            "X-CSRFToken": getCookie('csrftoken')
        },
        success: function (data, status, xhr) {
            var html = xhr.responseText;
            $('#messages').html($(html).find('#messages').html());
            getOrderTotal({});
        },
        error: function(xhr, status, errorThrown) {
            var html = xhr.responseText;
            $('#messages').html($(html).find('#messages').html());
        }
    });

    // Hide voucher modal as we submitted the form and empty the voucher input.
    $('.modal').modal('hide');
    $(voucherCodeElem).val('');
}