const twoFa = (function () {
    let disableDialog;
    let verificationDialog;

    let disableForUser;

    // stores intercepted event to dispatch it later after successful 2FA verification
    let pending = {
        resolve: undefined,
        reject: undefined,
    }

    return {
        disable2FaModal: function (event, user) {
            event.preventDefault();
            disableForUser = user;
            const modal = $("<div></div>").dialog_modal({
                passedArgs: ['', [], {
                    'header': '<h2>Disable two-factor authentication</h2>',
                    'body_url': MP_SITE_URL + '/directives/partials/disable_2fa_confirmation.php',
                    'onEscape': function () {
                    }
                }],
                addBodyClass: 'form-buttons',
                addMainWrapperClass: 'high'
            }).data('ui-dialog_modal');
            disableDialog = modal.instance();
        },

        disable2FaForUser: function (user) {
            const action = () => {
                common.globalSpinner.show();
                $.post('/twoFaApi/disable_to_user/' + (user || disableForUser))
                    .done(() => {
                        if (disableDialog !== null) {
                            disableDialog.modal('hide');
                        }
                        notify.success('2Fa successfully disabled.');
                        setTimeout(() => document.location.reload(), 1000);
                        common.globalSpinner.hide();
                    })
                    .fail((error) => {
                        common.globalSpinner.hide();
                        notify.error(error.responseText.trim());
                    });
            }
            this.asyncCheck2FaVerificationValid().then(action, () => {});
        },

        isVerificationNeeded: async function (verifyEveryTime = false) {
            const {
                two_factor_enabled = false,
                is2FaVerificationNeeded = false
            } = await fetch('/ProfileApi/user').then(response => response.json());
            return two_factor_enabled && (is2FaVerificationNeeded || verifyEveryTime)
        },

        asyncCheck2FaVerificationValid: function (verifyEveryTime = false) {
            return new Promise(async (resolve, reject) => {
                const isVerificationNeeded = await this.isVerificationNeeded(verifyEveryTime);
                if (!isVerificationNeeded) {
                    resolve();
                } else {
                    this.verification2FaModal();
                    pending = {resolve, reject};
                }
            });
        },

        verification2FaModal: function () {
            const modal = $("<div></div>").dialog_modal({
                passedArgs: ['', [], {
                    'header': '<h2>Confirm access</h2>',
                    'body_url': MP_SITE_URL + '/directives/partials/verification_2fa.php',
                    'onEscape': function () {
                    }
                }],
                addBodyClass: 'form-buttons',
                addMainWrapperClass: 'high',
                closeAction: function () {
                    verificationDialog = undefined;
                    if (pending.reject) {
                        pending.reject();
                    }
                }
            }).data('ui-dialog_modal');
            verificationDialog = modal.instance();
        },

        verify2Fa: function (code) {
            common.globalSpinner.show();
            $.post('/twoFaApi/verify', {code})
                .done(() => {
                    // close verification dialog
                    if (verificationDialog !== null) {
                        verificationDialog.modal('hide');
                    }

                    if (pending.resolve) {
                        pending.resolve();
                    }

                    $.cookie("2FaCode", code, {
                        expires: (new Date()).getTime() + 30 * 1000, // now + 30 seconds
                        path: '/',
                        secure: true,
                        httpOnly: true
                    });

                    common.globalSpinner.hide();
                })
                .fail((error) => {
                    common.globalSpinner.hide();
                    notify.error(error.responseText.trim());
                });
        },

        show2FaEnforcedModal: () => {
            const is2FaEnforcedKey = 'is2FaEnforced';
            if (localStorage.hasOwnProperty(is2FaEnforcedKey) || !modalThreshold.canBeShown()) {
                return;
            }
            fetch('/twoFaApi/mustUserEnable2Fa')
                .then(response => response.json())
                .then(({isEnforced}) => {
                    if (isEnforced) {
                        $("<div></div>")
                            .dialog_modal({
                                passedArgs: ['', [], {
                                    header: "<h2>Two-factor authentication required</h2>",
                                    body_url: MP_SITE_URL + '/directives/partials/enforce_2fa',
                                    onEscape: function () {
                                    }
                                }],
                                addBodyClass: 'form-buttons'
                            }).data('ui-dialog_modal');
                        localStorage.setItem(is2FaEnforcedKey, isEnforced);
                        modalThreshold.setShownTime()
                    }
                });
        },
        reset2FaEnforcementLock: username => {
            $.post('/twoFaApi/unlock_user/' + username)
                .done(() => {
                    notify.success('User successfully unlocked.');
                    setTimeout(() => document.location.reload(), 1000);
                    common.globalSpinner.hide();
                })
                .fail((error) => {
                    common.globalSpinner.hide();
                    notify.error(error.responseText.trim());
                });
        }
    };
})();

twoFa.show2FaEnforcedModal();
window.twoFa = twoFa;

