/**
 * 2007-2021 PrestaShop
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 *  @author    PrestaShop SA <contact@prestashop.com>
 *  @copyright 2007-2021 PrestaShop SA
 *  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free
 *   License (AFL 3.0) International Registered Trademark & Property of
 *   PrestaShop SA
 *
 * Don't forget to prefix your containers with your own identifier
 * to avoid any conflicts with others containers.
 */
(function (PS) {
    var checkExpireThreshold = 60000;
    var checkExpireHandler;
    var authorizing = false;
    var ajaxExecutor = null;
    var instanceId = null;
    var conditions = null;
    var merchantTrxId = null;
    var transactionCallback = '';

    document.addEventListener('DOMContentLoaded', function () {
        document.querySelector('body').addEventListener('checkout_error', function (e) {
            console.error(e);
        });

        var paymentOption = document.querySelector('[data-module-name^="addonpayments_"][name="payment-option"]');

        if (null === paymentOption || 'undefined' === (typeof paymentOption)) {
            return;
        }

        conditions = document.getElementById('conditions_to_approve[terms-and-conditions]');

        paymentOption.addEventListener('click', authorize);

        if (true !== addonpayments.is17) {
            var event = new MouseEvent('click', {
                bubbles: true,
                cancelable: true,
                view: window
            });
            // If cancelled, don't dispatch our event
            var canceled = !paymentOption.dispatchEvent(event);
        }

         if(null != conditions) {
            conditions.addEventListener('click', function(event){
                var target = event.target;
                var paymentOptionSelected = document.querySelector('[data-module-name^="addonpayments_"][name="payment-option"]:checked');
                var addonpaymentsForm = document.getElementById('addonForm');

                if (target.checked && null !== paymentOptionSelected) {

                    if(null !== addonpaymentsForm) {
                        var buttonSubmit = addonPaymentsForm.querySelector('button[type="submit"]');
                         buttonSubmit.disabled = false;
                         var error = document.getElementById('addonpayments-conditions-' + instanceId);
                        error.classList.add('hidden', 'hidden-sm-up', 'hidden-lg-down');
                    }else {
                        paymentOptionSelected.click();
                    }

                } else if( !target.checked && (null !== paymentOptionSelected || null !== addonpaymentsForm )) {
                    addonPaymentsForm = document.getElementById('addonForm')
                    var buttonSubmit = addonPaymentsForm.querySelector('button[type="submit"]');
                    buttonSubmit.disabled = true;
                }
            });
        }
    });

    function authorize(event) {
        if (true === authorizing) {
            event.preventDefault();
            return;
        }

        authorizing = true;
        clearTimeout(checkExpireHandler);
        var paymentOptionName = event.currentTarget.getAttribute('data-module-name');
        [, instanceId] = paymentOptionName.split('_');
        var paymentSolution = document.getElementById('addonpayments-' + instanceId);
        var authorizationUrl = paymentSolution.getAttribute('data-authorize-callback');
        window.addEventListener('error', handleGlobalError);

        try {
             if(null != conditions && !conditions.checked) {
                 var error = document.getElementById('addonpayments-conditions-' + instanceId);
                 error.classList.remove('hidden', 'hidden-sm-up', 'hidden-lg-down');
                 authorizing = false;
                 return;
            }
            if (null === paymentSolution || 'undefined' === (typeof paymentSolution)) {
                throw new RuntimeError(
                    'Could not find payment solution ' + instanceId,
                    addonpayments.translations.authorizationFailed
                );
            }

            resetStatus();
            requestAuthorizationToken(authorizationUrl, renderCashier);
        } catch (error) {
            var message = addonpayments.translations.unknownError;
            if (error.name === 'RuntimeError') {
                message = error.customerMessage;
            }
            showMessage(instanceId, 'error', message);
            console.error(error);
            authorizing = false;
            clearTimeout(checkExpireHandler);
        }
    }

    function handleGlobalError(error) {
        authorizing = false;
        ajaxExecutor.abort();
        clearTimeout(checkExpireHandler);

        if (-1 !== error.filename.indexOf('all-paysol')
            && null !== instanceId
            && 'undefined' !== typeof instanceId) {
            showMessage(instanceId,  'error', addonpayments.translations.unknownError);
        }
    }

    function resetStatus() {
        var paymentSolution = document.getElementById('addonpayments-' + instanceId + '');
        paymentSolution.querySelectorAll('[role="alert"]').forEach(function (_alert) {
            _alert.classList.add('hidden');
            _alert.classList.add('hidden-sm-up');
            _alert.classList.add('hidden-lg-down');
        });
    }

    function requestAuthorizationToken(authorizationUrl, callback) {
        ajaxExecutor = new XMLHttpRequest();
        ajaxExecutor.onreadystatechange = function () {
            // Only run if the request is complete
            if (ajaxExecutor.readyState !== 4) return;
            if (ajaxExecutor.status >= 200 && ajaxExecutor.status < 300) {
                authorizing = false;
                var data;
                try {
                    data = JSON.parse(ajaxExecutor.response);
                } catch (error) {
                    throw new RuntimeError('Invalid authorization response', addonpayments.translations.authorizationFailed);
                }

                if (data.hasOwnProperty('error')) {
                    throw new RuntimeError(data.error.message, addonpayments.translations.authorizationFailed);
                }

                callback(data);
            }

            if (ajaxExecutor.status >= 400) {
                throw new RuntimeError('Authorization failed', addonpayments.translations.authorizationFailed);
            }
        };

        ajaxExecutor.addEventListener('timeout', function (e) {
            console.debug(e);
            throw new RuntimeError('Authorization timed out', addonpayments.translations.authorizationFailed);
        });
        ajaxExecutor.open('POST', authorizationUrl);
        ajaxExecutor.setRequestHeader('Accept', 'application/json');
        ajaxExecutor.send();
    }

    function showMessage(instanceId, type, message) {
        var error = document.getElementById('addonpayments-' + type + '-' + instanceId);
        error.textContent = message;
        error.classList.remove('hidden');
        error.classList.remove('hidden-sm-up');
        error.classList.remove('hidden-lg-down');
    }

    function showDismissableMessage(instanceId, type, message) {
        var error = document.getElementById('addonpayments-' + type + '-' + instanceId);
        error.innerHTML = message + '<button type="button" class="close" data-dismiss="alert">&times;</button>';
        error.classList.remove('hidden');
        error.classList.remove('hidden-sm-up');
        error.classList.remove('hidden-lg-down');
    }

    /**
     * Render cashier
     * @param  {Object} authData billing address details
     */
    function renderCashier(authData) {
        try {
            var theme = 'string' === typeof addonpayments.style ? EPGJS_STYLE[addonpayments.style] : addonpayments.style;
            EPGJS_COMM.setEpgBaseUrl(authData.url);
            EPGJS_STYLE.setCssTheme(theme);
            EPGJS.setShowAllPaysolToRegisterAndQuickDeposit(true);
            EPGJS_COMM.setMerchantRegisterAccountCallback(registerAccountCallback);
            EPGJS_COMM.setRegisterAccountErrorCallback(registerAccountErrorCallback);
            EPGJS_COMM.setMerchantPrePayCallback(prepayCallback);
            EPGJS.setPrePayAccountErrorCallback(prepayErrorCallback);
            EPGJS_I18N.setLang(addonpayments.langcode);
            EPGJS_I18N.setI18n(addonpayments.i18n);

            window.addEventListener('message', function (e) {
                // console.log(e);
            });

            EPGJS.renderIntegratedCashier(authData.token, 'epgjs-cashier-div');

            let [decimalSeparator, thousandSeparator] = addonpayments.currency.specifications.symbol;

            EPGJS.setInitPaysolParam({
                "amount": addonpayments.amount * 100,
                "currency": addonpayments.currency.iso_code,
                "language": addonpayments.language.iso_code,
                "locale": addonpayments.language.locale,
                "decimalSeparator": decimalSeparator,
                "thousandSeparator": thousandSeparator,
                "widgetCheckoutStyle": {"color": "#4CC6CD", "branding": "lending_hub"},
                "widgetSimulationConditionsProduct": addonpayments.banner.nemuruProduct,
                "widgetSimulationStyle": "width: 100%;text-align:center",
                "widgetSimulationBranding": "lending_hub",
                "widgetSimulationVariant": "select",
                "widgetSimulationColor": "#f4aeeb"
            });

            checkTokenExpiration(authData.instanceId, authData.validUntil);

        } catch (error) {
            // @TODO Handle typed errors from API.
            throw new RuntimeError(error.message, addonpayments.translations.unknownError);
        }
    }

    function registerAccountCallback(payload) {
        resetStatus();
        // @TODO Only credit cards are allowed to be registered at this time.
        if ('CreditCards' !== payload.paymentMethod) {
            showDismissableMessage(instanceId, 'info', addonpayments.translations.registrationSuccess);
            return;
        }

        var paymentSolution = document.getElementById('addonpayments-' + instanceId);
        ajaxExecutor = new XMLHttpRequest();
        ajaxExecutor.onreadystatechange = function () {
            // Only run if the request is complete
            if (ajaxExecutor.readyState !== 4) return;
            if (ajaxExecutor.status >= 200 && ajaxExecutor.status < 300) {
                authorizing = false;
                var data;
                try {
                    data = JSON.parse(ajaxExecutor.response);
                } catch (error) {
                    throw new RuntimeError('Account registration returned an invalid response', addonpayments.translations.authorizationFailed);
                }

                if (data.hasOwnProperty('error')) {
                    throw new RuntimeError(data.error.message, addonpayments.translations.authorizationFailed);
                }

                if (false === data.success) {
                    showDismissableMessage(instanceId, 'warning', addonpayments.translations.registrationFailed);
                    return;
                }

                showDismissableMessage(instanceId, 'info', addonpayments.translations.registrationSuccess);
                return;
            }

            if (ajaxExecutor.status >= 400) {
                throw new RuntimeError('Account registration failed', addonpayments.translations.authorizationFailed);
            }
        };

        ajaxExecutor.addEventListener('timeout', function (e) {
            console.debug(e);
            throw new RuntimeError('Account regstration timed out', addonpayments.translations.authorizationFailed);
        });
        ajaxExecutor.open('POST', paymentSolution.getAttribute('data-register-callback'));
        ajaxExecutor.setRequestHeader('Accept', 'application/json');
        ajaxExecutor.setRequestHeader('Content-Type', 'application/json');
        ajaxExecutor.send(JSON.stringify(payload));
    }

    function registerAccountErrorCallback(data) {
        try {
            switch (true) {
                case (data.message.indexOf('expired') !== -1):
                    var expired = document.getElementById('addonpayments-expired-' + addonpayments.instance);
                    expired.classList.remove('hidden');
                    expired.classList.remove('hidden-sm-up');
                    expired.classList.remove('hidden-lg-down');
                    setTimeout(doReload, 2500);
                    break;
                case (data.message.indexOf('Reached limit accounts for the paysol') !== -1):
                    var error = document.getElementById('addonpayments-error-' + addonpayments.instance);
                    error.textContent = addonpayments.translations.reachedPaysolLimit;
                    error.classList.remove('hidden');
                    error.classList.remove('hidden-sm-up');
                    error.classList.remove('hidden-lg-down');
                    break;
                default:
                    var error = document.getElementById('addonpayments-error-' + addonpayments.instance);
                    error.textContent = addonpayments.translations.unknownError;
                    error.classList.remove('hidden');
                    error.classList.remove('hidden-sm-up');
                    error.classList.remove('hidden-lg-down');
                    console.debug(data);
            }
        } catch (e) {
            console.error(e);
        }
    }

    function prepayCallback(prepayData) {
        var prepayId = 'addonpayments-prepay-' + instanceId;
        var prepayForm = document.getElementById(prepayId);
        var responseElement = document.createElement('input');
        var paymentMethod = document.getElementById('addonForm');
        var rememberMeInput = document.querySelector('#epgjs_paymentmethod_payment_container input[name = "rememberMe"]');

        responseElement.setAttribute('id', prepayId + '__response');
        responseElement.setAttribute('type', 'hidden');
        responseElement.setAttribute('name', 'prepayResponse');

        prepayData.customerId = prepayForm.getAttribute('data-customer');
        prepayData.paymentMethod = paymentMethod.getAttribute('data-pmname').toLowerCase();
        prepayData.rememberMe = rememberMeInput !== null && !!rememberMeInput.checked;
        responseElement.value = JSON.stringify(prepayData);

        prepayForm.appendChild(responseElement);

        if ('quix' === prepayData.paymentMethod) {
            prepaySubmit();
        } else {
            prepayForm.submit();
        }
    }

    function prepayErrorCallback(code, data) {
        try {
            data = JSON.parse(data);
            switch (true) {
                case (data.errorMessage.indexOf('expired') !== -1):
                    var expired = document.getElementById('addonpayments-expired-' + instanceId);
                    expired.classList.remove('hidden');
                    expired.classList.remove('hidden-sm-up');
                    expired.classList.remove('hidden-lg-down');
                    setTimeout(doReload, 2500);
                    break;
                default:
                    var error = document.getElementById('addonpayments-error-' + instanceId);
                    error.textContent = addonpayments.translations.unknownError;
                    error.classList.remove('hidden');
                    error.classList.remove('hidden-sm-up');
                    error.classList.remove('hidden-lg-down');
                    console.error(data);
            }
        } catch (e) {
            console.error(e);
        }
    }

    function prepaySubmit() {
        var prepayId = 'addonpayments-prepay-' + instanceId;
        var form = document.getElementById(prepayId);
        var data = new FormData(form);

        ajaxExecutor = new XMLHttpRequest();

        ajaxExecutor.onreadystatechange = function () {
            // Only run if the request is complete
            if (ajaxExecutor.readyState !== 4) return;

            if (this.readyState === 4 && this.status === 200) {
                try {
                    var data = JSON.parse(ajaxExecutor.response);

                    if(data.hasError) {
                         window.location.replace(data.redirect);
                         return;
                    }

                    merchantTrxId = data.merchantTrxId;
                    transactionCallback = data.callback;

                    NEMURU.checkoutNemuru(data.nemuruAuthToken, data.nemuruCartHash);
                    NEMURU.setStatusCallback(nemuruStatusCallback);

                } catch (error) {
                    throw new RuntimeError('Invalid charge response');
                }
            }
        };

        ajaxExecutor.open(form.method, form.action);
        ajaxExecutor.setRequestHeader('Accept', 'application/json');
        ajaxExecutor.send(data);
    }

    function nemuruStatusCallback(e) {
        window.location.replace(transactionCallback)
    }

    function checkTokenExpiration(instanceId, expiresOn) {
        checkExpireHandler = setTimeout(function () {
            var aboutToExpire = document.getElementById('addonpayments-timeout-' + instanceId);
            var expired = document.getElementById('addonpayments-expired-' + instanceId);
            var currentTime = Date.now();
            var unit = (60 * 1000);
            var expiration = ((expiresOn - currentTime) / unit).toFixed(0);

            if (expiresOn <= (currentTime + checkExpireThreshold)) {
                aboutToExpire.classList.add('hidden');
                aboutToExpire.classList.add('hidden-sm-up');
                aboutToExpire.classList.add('hidden-lg-down');
                expired.classList.remove('hidden');
                expired.classList.remove('hidden-sm-up');
                expired.classList.remove('hidden-lg-down');
                setTimeout(doReload, 2500);
                return;
            }

            if ((expiration * unit) - (checkExpireThreshold * 2) <= checkExpireThreshold) {
                aboutToExpire.classList.remove('hidden');
                aboutToExpire.classList.remove('hidden-sm-up');
                aboutToExpire.classList.remove('hidden-lg-down');
            }

            checkTokenExpiration(instanceId, expiresOn);
        }, checkExpireThreshold);
    }

    function doReload(e) {
        if (null !== e && 'undefined' !== (typeof e)) {
            e.preventDefault();
        }

        window.location.reload(true);
    }

    function RuntimeError(message, customerMessage, fileName, lineNumber) {
        var instance = new Error(message, fileName, lineNumber);
        instance.name = 'RuntimeError';
        instance.customerMessage = customerMessage;
        Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
        if (Error.captureStackTrace) {
            Error.captureStackTrace(instance, RuntimeError);
        }
        return instance;
    }

    RuntimeError.prototype = Object.create(Error.prototype, {
        constructor: {
            value: Error,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });

    if (Object.setPrototypeOf){
        Object.setPrototypeOf(RuntimeError, Error);
    } else {
        RuntimeError.__proto__ = Error;
    }
})(window.prestashop, window.addonpayments);
