$.getScript('https://www.google.com/recaptcha/api.js', function () {
    const siteKey = window.recaptchaVars.siteKey;

    if (!siteKey) {
        console.error('Missing reCaptcha siteKey');
    }

    const captchas = document.querySelectorAll('.captcha');
    captchas.forEach((captcha) => {
        grecaptcha.ready(() => {
            try {
                captcha.classList.add('g-recaptcha');

                // get reference to containing form
                const parentForm = captcha.closest('form');

                if (!parentForm) {
                    console.error('reCaptcha must be within a form element.');
                    return;
                }

                const CAPTCHA_EMELEMENT_WIDTH = 304;
                const captchaResponsive = captcha.classList.contains('captcha-responsive') && parentForm.width < CAPTCHA_EMELEMENT_WIDTH;

                grecaptcha.render(captcha, {
                    'sitekey': siteKey,
                    'callback': function (e, formEl = parentForm) {
                        // get reference to #recaptchaConfirmedHidden within containing form and update value to 1
                        const recaptchaConfirmedHidden = formEl.querySelector('#recaptchaConfirmedHidden');
                        if (recaptchaConfirmedHidden) {
                            // Flag the recaptcha response as valid.
                            recaptchaConfirmedHidden.value = 1;
                        }

                        // once confirmed, remove the error if present
                        if ($('.js-grecaptcha-error').length) {
                            $('.js-grecaptcha-error').remove();
                        }
                    },
                    'size': captchaResponsive ? 'compact' : 'normal'
                });
            } catch (error) {
                // error likely due this Captcha element being previously rendered.
            }
        });
    });
});

/**
 * @pre The recaptchaConfirmedHidden element must be present on the indicated form at the top level, no nesting.
 * @param $form jquery wrapped form instance
 * @param errorMessageSelector  Selector used to target error message area.  Defaults to .js-section-error.
 * @return TRUE if validated, FALSE if validation failed
 */
function handle_grecaptcha_presubmit($form, errorMessageSelector) {
    const captchaConfirmed = $form.find('#recaptchaConfirmedHidden').val();

    if (!errorMessageSelector) {
        errorMessageSelector = '.js-section-error'
    }

    if (captchaConfirmed !== "1") {
        $(errorMessageSelector).html('' +
            '<div class="js-section-error js-grecaptcha-error">' +
            '<div class="alert alert-danger alert-dismissible js-page-message show fade in" role="alert">' +
            '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true"><i class="ion-ios-close"></i></span></button>' +
            '<span class="js-message">' +
            '<ul class="uiMessageList list-unstyled">' +
            '<li>Error: <span class="validation-title">Please complete the captcha</span></li>' +
            '</ul>' +
            '</span>' +
            '</div>' +
            '</div>'
        );

        $(errorMessageSelector).show();

        $form.data("stopSubmit", true);
        return false;
    } else {
        $form.removeData("stopSubmit");
        return true;
    }
}

function handle_grecaptcha_modal_presubmit($form, errorMessageSelector, modalSelector) {
    const captchaConfirmed = $form.find('#recaptchaConfirmedHidden').val();

    if (!errorMessageSelector) {
        errorMessageSelector = '.js-captcha-error'
    }

    if (!modalSelector) {
        modalSelector = '.js-captcha-modal'
    }

    if (captchaConfirmed !== "1") {
        const $recaptchaModal = $(modalSelector);

        // if modal is already open show error message to tell the user to complete the captcha
        if ($recaptchaModal.hasClass('show')) {
            handle_grecaptcha_presubmit($form, errorMessageSelector);
        }

        // show the modal
        $recaptchaModal.modal({
            show: true
        });

        $form.data("stopSubmit", true);
        return false;
    } else {
        $form.removeData("stopSubmit");
        return true;
    }
}

/**
 * reset grecaptcha and clear $recaptchaConfirmedHidden value to force captcha validation check again
 * @param $form
 */
function reset_grecaptcha($form) {
    const $recaptchaConfirmedHidden = $form.find('#recaptchaConfirmedHidden');

    if ($recaptchaConfirmedHidden.length) {
        $recaptchaConfirmedHidden.val('');
    }

    if (window.grecaptcha) {
        grecaptcha.reset();
    }
}
