import {toFormData} from 'Global/Form/formUtils'
import {activeLoader, desactiveLoader} from 'Global/Ajax/loader'
import {activePopupError} from 'Global/Popup/popupInline'

// creation du unserialize
function unserialize(data) {
    data = data.split('&');
    var response = {};
    for (var s of data){
        var newData = s.split('=');
        response[newData[0]] = newData[1];
    }
    return response;
}

export const ajax = {
    _boot: () => {
        // Implementation du CSRF
        $.ajaxPrefilter(function (options) {
        
            if (options.type.toLowerCase() != 'post') {
                return;
            }

            if( options.data instanceof FormData ) {
                if( ! options.data.has('tokenCSRF') ) {
                    options.data.append($('#tokenCSRF').attr('name'), $('#tokenCSRF').val());
                }
                return;
            }

            if(!options.mimeType || options.mimeType == '') {
                if (typeof options.data === 'string' || options.data instanceof String) {
                    var dataSerrialize = options.data;
                    if('tokenCSRF' in unserialize(dataSerrialize) == false) {
                        options.data += '&' + encodeURIComponent($('#tokenCSRF').attr('name')) + '='+encodeURIComponent($('#tokenCSRF').val());
            
                        if (options.data.charAt(0) == '&') {
                            options.data = options.data.substr(1);
                        }
                    }
                } else if (typeof options.data == 'object') {
                    options.data.tokenCSRF = $('#tokenCSRF').val();
                }
            } else {
                options.data.append($('#tokenCSRF').attr('name'), $('#tokenCSRF').val());
            }

        });
    }
}

/**
 * @param String path  
 * @param FormData|object|null data 
 */
export function ajaxSimple(path, data, fnSuccess, fnError = null) {
    $.ajax({
        url: path,
        type: 'POST',
        data: toFormData(data),
        contentType: false,
        processData: false,
        success: function (response, status, xhr) {
            if (xhr.getResponseHeader('Content-Type') == 'application/json') {
                response = JSON.parse(xhr.responseText);
            }

            fnSuccess(response, status, xhr, data);
            desactiveLoader();
        },
        error: fnError ?? (function (xhr) {
            activePopupError(
                window.oxaproc.trad['Erreur validation'],
                xhr.responseText,
                'modal_small'
            );

            // Assume http 400 -> show constraint validation error
            desactiveLoader();
        })
    });
    return false;
}

/**
 * usage :  
 *     onsubmit="return ajaxSubmit(event);"
 * @param SubmitEvent|HTMLFormElement event  
 * @param FormData|null formDataSup 
 */
export function ajaxSubmit(event, formDataSup) {
    
    // Get form
    let form = event;
    if (event instanceof Event) {
        event.preventDefault();
        form = event.target;
    }

    activeLoader();
    let formData = new FormData(form);

    // Submitter data
    if (event.submitter && event.submitter.name) {
        formData.append(
            event.submitter.name,
            event.submitter.value
        );
    }

    // Merge formData
    if (formDataSup !== undefined) {
        for (const pair of formDataSup.entries()) {
            formData.append(pair[0], pair[1]);
        }
    }

    $.ajax({
        url: form.getAttribute('action'),
        type: 'POST',
        data: formData,
        contentType: false,
        processData: false,
        success: function (response, status, xhr) {
            // Case : file download
            if (xhr.getResponseHeader('Content-Disposition')?.startsWith('attachment')) {
                const fileName = (
                    xhr.getResponseHeader('Content-Disposition')
                    .match(/filename="(.*?)"/) ?? []
                )[1] ?? 'file';

                // TODO : factorize into its own function
                // Simulate browser native file download
                const url = window.URL.createObjectURL(new Blob(
                    [xhr.responseText],
                    {type: "application/octet-stream"}
                ));
                const a = document.createElement('a');
                a.style.display = 'none';
                a.href = url;
                a.download = fileName;
                document.body.appendChild(a);
                a.click();
                window.URL.revokeObjectURL(url);
                
                desactiveLoader();
                return;
            }
            if (xhr.getResponseHeader('Content-Type') == 'application/json') {
                response = JSON.parse(xhr.responseText);
            }

            // Call success callback
            if (form.hasAttribute('data-onsuccess')) {
                window.action[ form.getAttribute('data-onsuccess') ](response, status, xhr, form);
                return;
            }
            if (form.hasAttribute('data-onsuccess-goto')) {
                location.href = form.getAttribute('data-onsuccess-goto');
                return;
            }
            desactiveLoader();
        },
        error: function (xhr) {

            // Case : json response (Erreur non bloquante)
            if (xhr.getResponseHeader('Content-Type') == 'application/json') {
                const response = JSON.parse(xhr.responseText);

                // Failsafe : only handle response 'confirm' for json content type
                if (response.type != 'confirm') {
                    throw '!!!';
                }

                desactiveLoader();
                activePopup(
                    window.oxaproc.trad['Erreur validation'],
                    response.popupHtml,
                    'modal_small'
                );
                document.querySelector('[data-popupwarning-cancel]')
                    .addEventListener('click', function () {
                        desactivePopup();
                    });
                document.querySelector('[data-popupwarning-continue]')
                    .addEventListener('click', function () {
                        // Resend form with confirm
                        formData = new FormData();
                        formData.append('confirm', '1');
                        ajaxSubmit(form, formData);
                        desactivePopup();
                    });
                return;
            }

            // Call error callback
            if (form.hasAttribute('data-onerror')) {
                window.action[ form.getAttribute('data-onerror') ](xhr, form);
                return;
            }

            // Case : form has an error displayer
            let wrapperError = form.querySelector('[data-form-error]');
            if (wrapperError) {
                wrapperError.innerHTML = xhr.responseText;
                desactiveLoader();
                wrapperError.scrollIntoView({behavior: 'smooth', block: 'nearest'});
                return;
            }

            // Assume http 400 -> show constraint validation error
            desactiveLoader();
            activePopupError(
                window.oxaproc.trad['Erreur validation'],
                xhr.responseText,
                'modal_small'
            );
        }
    });
    return false;
}