/* globals jQuery, Give */
(function ($) {
    const templateL10n = window.sequoiaTemplateL10n;
    const templateOptions = window.sequoiaTemplateOptions;
    const $container = $('.give-embed-form');
    const $advanceButton = $('.advance-btn', $container);
    const $backButton = $('.back-btn');
    const $navigatorTitle = $('.give-form-navigator .title');
    const $paymentGatewayContainer = $('#give-payment-mode-select');
    let gatewayAnimating = false;
    const {wp: parentWp} = window.parent;

    // Make donation form block selectable in editor
    if (parentWp && parentWp.data) {
        $container.on('click', function () {
            const blockId = window.frameElement.closest('.wp-block').getAttribute('data-block');
            parentWp.data.dispatch('core/block-editor').selectBlock(blockId);
        });
    }

    // Attach the navigator to the window as an API for changing parts.
    const navigator = (window.formNavigator = {
        currentStep: templateOptions.introduction.enabled === 'enabled' ? 0 : 1,
        animating: false,
        firstFocus: false,
        goToStep: (step) => {
            // Adjust body height before animating step, to prevent choppy iframe resizing
            // Compare next step to current step, and increase body height if next step is taller.
            const nextStepHeight = steps[step].title
                ? $(steps[step].selector).height() + 50
                : $(steps[step].selector).height();
            const currentStepHeight = steps[navigator.currentStep].title
                ? $(steps[navigator.currentStep].selector).height() + 50
                : $(steps[navigator.currentStep].selector).height();
            if (nextStepHeight > currentStepHeight) {
                $('.give-form-templates').css('min-height', `${nextStepHeight + 123}px`);
            } else {
                // Delay setting body height if next step is shorter than current step
                setTimeout(function () {
                    $('.give-form-templates').css('min-height', `${nextStepHeight + 123}px`);
                }, 200);
            }

            $('.step-tracker').removeClass('current');
            $('.step-tracker[data-step="' + step + '"]').addClass('current');

            // Handle introduction step (whether disabled or not).
            if (templateOptions.introduction.enabled === 'disabled') {
                if ($('.step-tracker').length === 3) {
                    $('.step-tracker').remove();
                }

                step = step > 0 ? step : 1;
                if (step === 1) {
                    $('.back-btn', $container).hide();
                } else {
                    $('.back-btn', $container).show();
                }

                $('.give-form-navigator', $container).addClass('nav-visible');
                $(steps[step].selector).css('padding-top', '50px');
            } else if (step === 0) {
                // First  step is enabled.
                $('.give-form-navigator', $container).removeClass('nav-visible');
                $(steps[step].selector).css('padding-top', '');
            } else {
                // Other steps besides intro and payment amounts:
                $('.give-form-navigator', $container).addClass('nav-visible');
                $(steps[step].selector).css('padding-top', '50px');
                // Scroll to top after animation finished
                // @see https://github.com/impress-org/givewp/issues/5969
                scrollToIframeTop();
            }

            if (steps[step].title) {
                $navigatorTitle.text(steps[step].title);
            }

            const hide = steps.map((obj, index) => {
                if (index === step || index === navigator.currentStep) {
                    return null;
                }
                return obj.selector;
            });
            const hideSelector = hide.filter(Boolean).join(', ');

            $(hideSelector).hide();

            if (navigator.currentStep !== step) {
                const directionClasses = 'slide-in-right slide-in-left slide-out-right slide-out-left';
                const outDirection = navigator.currentStep < step ? 'left' : 'right';
                const inDirection = navigator.currentStep < step ? 'right' : 'left';
                $(steps[navigator.currentStep].selector)
                    .removeClass(directionClasses)
                    .addClass(`slide-out-${outDirection}`);
                $(steps[step].selector).show().removeClass(directionClasses).addClass(`slide-in-${inDirection}`);
            }
            navigator.currentStep = step;

            setTimeout(function () {
                setupTabOrder();
                // Do not auto-focus form on the page load if the first step is disabled
                if (!navigator.firstFocus && templateOptions.introduction.enabled === 'disabled') {
                    return (navigator.firstFocus = true);
                }
                if (steps[navigator.currentStep].firstFocus) {
                    $(steps[navigator.currentStep].firstFocus).trigger('focus');
                }
            }, 200);
        },
        init: () => {
            steps.forEach((step) => {
                if (step.setup !== undefined) {
                    step.setup();
                }
                $(step.selector).css('position', 'absolute');
            });
            $advanceButton.on('click', function (e) {
                e.preventDefault();
                navigator.forward();
            });
            $backButton.on('click', function (e) {
                e.preventDefault();
                navigator.back();
            });
            $('.step-tracker').on('click', function (e) {
                e.preventDefault();
                navigator.goToStep(parseInt($(e.target).attr('data-step')));
            });
            setupHeightChangeCallback(function (height) {
                if (gatewayAnimating === false) {
                    $('.form-footer').css('transition', 'margin-top 0.2s ease');
                } else {
                    $('.form-footer').css('transition', '');
                }
                $('.form-footer').css('margin-top', `${height}px`);
            });

            // If Fee Recovery input is not inside any step, move it to above payment options
            if ($('.give-fee-recovery-donors-choice').parent().hasClass('give-form')) {
                $('#give_checkout_user_info').after($('.give-fee-recovery-donors-choice'));
            }
            navigator.goToStep(getInitialStep());
        },
        back: () => {
            const prevStep = navigator.currentStep !== 0 ? navigator.currentStep - 1 : 0;
            navigator.goToStep(prevStep);
            navigator.currentStep = prevStep;
        },
        forward: () => {
            const nextStep = navigator.currentStep !== null ? navigator.currentStep + 1 : 1;
            navigator.goToStep(nextStep);
            navigator.currentStep = nextStep;
        },
    });

    const steps = [
        {
            id: 'introduction',
            title: null,
            selector: '.give-section.introduction',
            label: templateOptions.introduction.donate_label,
            showErrors: false,
            tabOrder: ['.introduction .advance-btn', '.step-tracker'],
        },
        {
            id: 'choose-amount',
            title: templateOptions.payment_amount.header_label,
            selector: '.give-section.choose-amount',
            label: templateOptions.payment_amount.next_label,
            showErrors: false,
            tabOrder: [
                'select.give-cs-select-currency',
                'input.give-amount-top',
                '.give-donation-levels-wrap button',
                '.give-recurring-period',
                '.give-recurring-donors-choice-period',
                '.give_fee_mode_checkbox',
                '.choose-amount .advance-btn',
                '.step-tracker',
                '.back-btn',
            ],
            firstFocus: '.give-default-level',
            setup: () => {
                // Dynamically set grid columns based on number of buttons
                const buttonCount = $('.give-donation-level-btn').length;
                if (buttonCount === 1) {
                    $('.give-donation-levels-wrap').attr('style', 'display: none!important;');
                } else if (buttonCount % 2 === 0 && buttonCount < 6) {
                    $('.give-donation-levels-wrap').css('grid-template-columns', 'repeat(2, minmax(0, 1fr))');
                }

                $('#give-amount').on('blur', function () {
                    if (!Give.form.fn.isValidDonationAmount($('form'))) {
                        $('.advance-btn').attr('disabled', true);
                    } else {
                        $('.advance-btn').attr('disabled', false);
                    }
                });
                $('.give-donation-level-btn').each(function () {
                    const hasTooltip = $(this).attr('has-tooltip');
                    if (hasTooltip) {
                        return;
                    }

                    const value = $(this).attr('value');
                    const text = $(this).text();
                    const $form = $('form');
                    const symbol = Give.form.fn.getInfo('currency_symbol', $form);
                    const position = Give.form.fn.getInfo('currency_position', $form);

                    if (value !== 'custom') {
                        const html =
                            position === 'before'
                                ? `<div class="currency currency--before">${symbol}</div>${value}`
                                : `${value}<div class="currency currency--after">${symbol}</div>`;
                        $(this).html(html);
                    }

                    // Setup string to check tooltip label ga
                    const compare = position === 'before' ? symbol + value : value + symbol;
                    // Setup tooltip unless for custom donation level, or if level label matches value
                    if (value !== 'custom' && text !== compare) {
                        const wrap = document.createElement('span');
                        wrap.classList.add('give-tooltip', 'hint--top', 'hint--bounce');
                        if (text.length < 50) {
                            wrap.classList.add('narrow');
                        }
                        wrap.style.width = '100%';
                        wrap.setAttribute('aria-label', text.length < 50 ? text : text.substr(0, 50) + '...');
                        $(this).wrap(wrap);
                        $(this).attr('has-tooltip', true);
                    }
                });
            },
        },
        {
            id: 'payment',
            title: templateOptions.payment_information.header_label,
            label: templateOptions.payment_information.checkout_label,
            selector: '.give-section.payment',
            showErrors: true,
            tabOrder: [
                '.payment input, .payment a, .payment button, .payment select, .payment multiselect, .payment textarea, .payment .button',
                '.give-submit',
                '.step-tracker',
                '.back-btn',
            ],
            firstFocus: '#give-first',
            setup: () => {
                // Setup payment information screen

                $('.give-section.payment').on(
                    'click',
                    '.give-cancel-login, .give-checkout-register-cancel',
                    clearLoginNotices
                );

                // Show Sequoia loader on click/touchend
                $('.give-section.payment').on('click touchend', 'input[name="give_login_submit"]', function () {
                    //Override submit loader with Sequoia loader
                    $('input[name="give_login_submit"] + .give-loading-animation')
                        .removeClass('give-loading-animation')
                        .addClass('sequoia-loader spinning');
                });

                // Remove purchase_loading text
                window.give_global_vars.purchase_loading = '';

                // Move errors
                $('.give_error').each(function () {
                    moveErrorNotice($(this));
                });

                // Setup anonymous donations opt-in event listeners
                setupCheckbox({
                    container: '#give-anonymous-donation-wrap label',
                    label: '#give-anonymous-donation-wrap label',
                    input: '#give-anonymous-donation',
                });

                // Setup recurring donations opt-in event listeners
                setupCheckbox({
                    container: '.give-recurring-donors-choice',
                    label: '.give-recurring-donors-choice label',
                    input: 'input[name="give-recurring-period"]',
                });

                // Setup fee recovery opt-in event listeners
                setupCheckbox({
                    container: '.give-fee-recovery-donors-choice',
                    label: '.give-fee-message-label-text',
                    input: 'input[name="give_fee_mode_checkbox"]',
                });

                // Setup activecampaign opt-in event listeners
                setupCheckbox({
                    container: '.give-activecampaign-fieldset',
                    label: '.give-activecampaign-optin-label',
                    input: '.give-activecampaign-optin-input',
                });

                // Setup mailchimp opt-in event listeners
                setupCheckbox({
                    container: '.give-mailchimp-fieldset',
                    label: '.give-mc-message-text',
                    input: 'input[name="give_mailchimp_signup"]',
                });

                // Setup constant contact opt-in event listeners
                setupCheckbox({
                    container: '.give-constant-contact-fieldset',
                    label: '.give-constant-contact-fieldset span',
                    input: 'input[name="give_constant_contact_signup"]',
                });

                // Setup terms and conditions opt-in event listeners
                setupCheckbox({
                    container: '#give_terms_agreement',
                    label: '#give_terms_agreement label',
                    input: 'input[name="give_agree_to_terms"]',
                });

                // Show Sequoia loader on click/touchend
                $('body.give-form-templates').on(
                    'click touchend',
                    'form.give-form input[name="give-purchase"].give-submit',
                    function () {
                        //Override submit loader with Sequoia loader
                        $('#give-purchase-button + .give-loading-animation')
                            .removeClass('give-loading-animation')
                            .addClass('sequoia-loader');

                        // Only show spinner if form is valid
                        if ($('form').get(0).checkValidity()) {
                            $('.sequoia-loader').addClass('spinning');
                        }
                    }
                );

                // Go to choose amount step when donation maximum error is clicked
                $('body.give-form-templates').on('click touchend', '#give_error_invalid_donation_maximum', function () {
                    // Go to choose amount step
                    navigator.goToStep(1);
                });

                // Go to choose amount step when invalid donation error is clicked
                $('body.give-form-templates').on('click touchend', '#give_error_invalid_donation_amount', function () {
                    // Go to choose amount step
                    navigator.goToStep(1);
                });

                // Setup gateway icons
                setupGatewayIcons();

                // Setup Form Field Manager input listeners
                setupFFMInputs();

                // Setup Icons for inputs
                setupInputIcons();

                const observer = new window.MutationObserver(function (mutations) {
                    mutations.forEach(function (mutation) {
                        if (!mutation.addedNodes) {
                            return;
                        }

                        for (let i = 0; i < mutation.addedNodes.length; i++) {
                            // do things to your newly added nodes here
                            const node = mutation.addedNodes[i];

                            if ($(node).find('.give_error').length > 0) {
                                moveErrorNotice($(node).find('.give_error'));
                                scrollToIframeTop();
                            }

                            if ($(node).children().hasClass('give_errors')) {
                                if (!$(node).parent().hasClass('donation-errors')) {
                                    $(node)
                                        .children('.give_errors')
                                        .each(function () {
                                            const notice = $(this);
                                            moveErrorNotice(notice);
                                        });
                                }
                                scrollToIframeTop();
                            }

                            if ($(node).hasClass('give_errors') && !$(node).parent().hasClass('donation-errors')) {
                                moveErrorNotice($(node));
                                $('.sequoia-loader').removeClass('spinning');
                                scrollToIframeTop();
                            }

                            if ($(node).attr('id') === 'give_tributes_address_state') {
                                const placeholder = $(node).attr('placeholder');
                                $(node).prepend(`<option selected disabled>${placeholder}</option>`);
                            }

                            if (
                                $(node).attr('name') === 'give_tributes_address_state' &&
                                $(node).attr('class').includes('give-input')
                            ) {
                                $(node).attr('placeholder', $(node).siblings('label').text().trim());
                            }

                            if ($(node).attr('id') && $(node).attr('id').includes('give-checkout-login-register')) {
                                setupRegistrationFormInputFields();
                                setupInputIcons();
                            }

                            if ($(node).prop('tagName') && $(node).prop('tagName').toLowerCase() === 'select') {
                                const placeholder = $(node).attr('placeholder');
                                if (placeholder) {
                                    $(node).prepend(`<option value="" disabled selected>${placeholder}</option>`);
                                }
                            }

                            if ($(node).find('.required[placeholder]').length) {
                                setupRequiredFieldPlaceholders(
                                    Array.from($(node).get(0).querySelectorAll('.required[placeholder]'))
                                );
                            }
                        }
                    });
                });

                observer.observe(document.body, {
                    childList: true,
                    subtree: true,
                    attributes: false,
                    characterData: false,
                });
            },
        },
    ];

    navigator.init();

    // Check if only a single gateway is enabled
    if ($paymentGatewayContainer.length && $paymentGatewayContainer.css('display') !== 'none') {
        // Move payment information section when document load.
        moveFieldsUnderPaymentGateway();

        // Move payment information section when gateway updated.
        $(document).on('give_gateway_loaded', function () {
            setTimeout(setupTabOrder, 200);

            moveFieldsUnderPaymentGateway();
            setupLegacyConsumerCheckboxAndRadio();
            setupRegistrationFormInputFields();
            setupFFMInputs();
            setupInputIcons();
            setupSelectInputs();

            $('#give_purchase_form_wrap').slideDown(200, function () {
                gatewayAnimating = false;
            });
        });
        $(document).on('Give:onPreGatewayLoad', function () {
            gatewayAnimating = true;
            $('#give_purchase_form_wrap').slideUp(200);
        });

        // Clear gateway related errors
        $(document).on('Give:onPreGatewayLoad', function () {
            const persistedNotices = ['give_error_test_mode'];

            $('.give_errors, .give_notices, .give_error').each(function () {
                if (!persistedNotices.includes($(this).attr('id'))) {
                    $(this).slideUp(200, function () {
                        $(this).remove();
                    });
                }
            });
        });
    } else {
        $('#give_purchase_form_wrap').addClass('give-single-gateway-wrap');
    }

    // Refresh personal information section.
    $(document).on('give_gateway_loaded', refreshPersonalInformationSection);

    // Setup fields.
    setupLegacyConsumerCheckboxAndRadio();
    setupSelectInputs();
    setupRegistrationFormInputFields();
    setupFFMInputs();
    setupInputIcons();
    setupRequiredFieldPlaceholders(Array.from(document.querySelectorAll('.give-form .required[placeholder]')));

    /**
     * Denote required fields as required by adding a asterisks (*) prefix to placeholder.
     *
     * @since 2.21.2
     *
     * @param {array} inputs An iteratable list of input elements.
     */
    function setupRequiredFieldPlaceholders(inputs) {
        inputs.map(function (input) {
            if ('*' !== input.placeholder.trim().slice(-1)) {
                input.placeholder = `${input.placeholder.trim()}*`;
            }
        });
    }

    /**
     * Move error notices to error notice container at the top of the payment section
     * @since 2.7.0
     * @since 2.12.0 Prevents a race condition that caused an error message not to be visible.
     * @param {node} node The error notice node to be moved
     */
    function moveErrorNotice(node) {
        //If the error is inside stripe payment button, do nothing
        if ($(node).parent().hasClass('give-stripe-payment-request-button')) {
            return;
        }

        // First check if specific donation notice container has been set up
        if ($('.donation-errors').length === 0) {
            $('.payment').prepend('<div class="donation-errors"></div>');
        }

        /**
         * @link https://github.com/impress-org/givewp/issues/5867
         *
         * This 1 millisecond timeout prevents a race condition between
         * the `.donation-errors` element being appended to the form
         * and relocation of the specific error message node.
         */
        setTimeout(function () {
            // If a specific notice does not already exist, proceed with moving the error
            if (
                typeof $('.donation-errors').html() !== undefined &&
                !$('.donation-errors').html().includes($(node).html())
            ) {
                $(node).appendTo('.donation-errors');
            } else {
                // If the specific notice already exists, do not add it
                $(node).remove();
            }
        }, 1);
    }

    /**
     * Setup registration form input fields.
     * @since 2.9.6
     */
    function setupRegistrationFormInputFields() {
        const handleInput = function (evt) {
            if (!$(evt.target).is('input')) {
                return;
            }

            if ($(evt.target).hasClass('give-disabled')) {
                return;
            }

            // Registration account fields only contains checkboxes.
            $(evt.target).closest('label').toggleClass('checked');
        };

        $('[id*="give-register-account-fields"]').off('click', handleInput).on('click', handleInput);
    }

    /**
     * Add listeners and starting states to FFM inputs
     * @since 2.7.0
     */
    function setupFFMInputs() {
        $('#give-ffm-section').off('click', handleFFMInput).on('click', handleFFMInput);

        $('#give-ffm-section input').each(function () {
            switch ($(this).prop('type')) {
                case 'checkbox': {
                    if ($(this).prop('checked')) {
                        $(this).parent().addClass('checked');
                    } else {
                        $(this).parent().removeClass('checked');
                    }
                    break;
                }
                case 'radio': {
                    if ($(this).prop('checked')) {
                        $(this).parent().addClass('selected');
                    } else {
                        $(this).parent().removeClass('selected');
                    }
                    break;
                }
            }
        });
    }

    /**
     * Handle updating label classes for FFM radios and checkboxes
     *
     * @since 2.7.0
     * @param {object} evt Reference to FFM input element click event
     */
    function handleFFMInput(evt) {
        if ($(evt.target).is('input')) {
            switch ($(evt.target).prop('type')) {
                case 'checkbox': {
                    $(evt.target).closest('label').toggleClass('checked');
                    break;
                }
                case 'radio': {
                    $(evt.target).closest('label').addClass('selected');
                    $(evt.target).parent().siblings().removeClass('selected');
                    break;
                }
            }
        }
    }

    /**
     * Move form field under payment gateway
     * @since 2.7.0
     */
    function moveFieldsUnderPaymentGateway() {
        // Check if donate fieldset area has been created, if not set it up below payment gateways
        // This area is necessary for correctly placing various elements (fee recovery notice, newsletters, submit button, etc)
        if ($('#donate-fieldset').length === 0) {
            $('.give-section.payment').append('<fieldset id="donate-fieldset"></fieldset>');
        }

        // Elements to move into donate fieldset (located at bottom of form)
        // The elements will appear in order of array
        const donateFieldsetElements = [
            '.give-constant-contact-fieldset',
            '.give-activecampaign-fieldset',
            '.give-mailchimp-fieldset',
            '#give_terms_agreement',
            '.give-donation-submit',
        ];

        // Handle moving elements into donate fieldset
        donateFieldsetElements.forEach(function (selector) {
            if ($(`#donate-fieldset  ${selector}`).length === 0) {
                $(`#donate-fieldset  ${selector}`).remove();
                $('#donate-fieldset').append($(`#give_purchase_form_wrap ${selector}`));
            } else if (
                $(`#donate-fieldset  ${selector}`).html() !== $(`#give_purchase_form_wrap  ${selector}`).html() &&
                $(`#give_purchase_form_wrap  ${selector}`).html() !== undefined
            ) {
                $(`#donate-fieldset  ${selector}`).remove();
                $('#donate-fieldset').append($(`#give_purchase_form_wrap ${selector}`));
            } else {
                $(`#give_purchase_form_wrap ${selector}`).remove();
            }
        });

        // Move purchase fields (credit card, billing, etc)
        $('li.give-gateway-option-selected').after($('#give_purchase_form_wrap'));

        // Add gateway class to fields wrapper, indicating which gateway is active
        const gatewayClass = 'gateway-' + $('.give-gateway-option-selected input').attr('value').replace('_', '-');
        $('#give_purchase_form_wrap').attr('class', gatewayClass);
    }

    /**
     * Refresh personal information section
     *
     * @since 2.7.0
     * @since 2.10.2 Rename function
     * @param {boolean} ev Event object
     * @param {object} response Response object
     * @param {number} formID Form ID
     */
    function refreshPersonalInformationSection(ev, response, formID) {
        if (navigator.currentStep === 2) {
            $('.give-form-templates').css('min-height', '');
        }

        const $form = $(`#${formID}`);

        // This function will run only for embed donation form.
        // Show payment information section fields.
        if ($form.parent().hasClass('give-embed-form')) {
            const data = {
                action: 'give_cancel_login',
                form_id: $form.find('[name="give-form-id"]').val(),
            };

            // AJAX get the payment fields.
            $.post(Give.fn.getGlobalVar('ajaxurl'), data, function (postResponse) {
                const container = $form.find('[id^=give-checkout-login-register]');

                // Remove existing personal information field if response contains new fields.
                if (container.length && postResponse.fields.includes('give_checkout_user_info')) {
                    $form.find('#give_checkout_user_info').remove();
                }

                container.replaceWith($.parseJSON(postResponse.fields));
                container.css({display: 'block'});

                $form.find('.give-submit-button-wrap').show();
            }).done(function () {
                // Trigger float-labels
                window.give_fl_trigger();

                setupInputIcons();
            });
        }
    }

    function setupInputIcon(selector, icon) {
        $(selector).each(function () {
            if ($(this).html() !== '' && $(this).html().includes(`<i class="fas fa-${icon}"></i>`) === false) {
                const property = isRTL() ? 'padding-right' : 'padding-left';
                $(this).prepend(`<i class="fas fa-${icon}"></i>`);
                $(this)
                    .children('input, selector')
                    .each(function () {
                        $(this).attr('style', property + ': 33px!important;');
                    });
            }
        });
    }

    function setupInputIcons() {
        setupInputIcon('#give-first-name-wrap', 'user');
        setupInputIcon('#give-email-wrap', 'envelope');
        setupInputIcon('#give-company-wrap', 'building');
        setupInputIcon('#date_field-wrap', 'calendar-alt');
        setupInputIcon('#url_field-wrap', 'globe');
        setupInputIcon('#phone_field-wrap', 'phone');
        setupInputIcon('#give-phone-wrap', 'phone');
        setupInputIcon('#email_field-wrap', 'envelope');
    }

    /**
     * Setup tab order for elements in form
     *
     * @since 2.7.0
     */
    function setupTabOrder() {
        $('select, button, input, textarea, multiselect, a').attr('tabindex', -1);

        const tabOrder = steps[navigator.currentStep].tabOrder;
        tabOrder.forEach((selector, index) => {
            $(selector).attr('tabindex', index + 1);
        });
    }

    /**
     * Loop through gateway li elements and setup fontawesome icons
     *
     * @since 2.7.0
     */
    function setupGatewayIcons() {
        $('#give-gateway-radio-list li').each(function () {
            const value = $('input', this).val();
            let icon;
            switch (value) {
                case 'manual':
                    icon = 'fas fa-tools';
                    break;
                case 'offline':
                    icon = 'fas fa-wallet';
                    break;
                case 'paypal':
                    icon = 'fab fa-paypal';
                    break;
                case 'stripe':
                    icon = 'far fa-credit-card';
                    break;
                case 'stripe_checkout':
                    icon = 'far fa-credit-card';
                    break;
                case 'stripe_sepa':
                    icon = 'fas fa-university';
                    break;
                case 'stripe_ach':
                    icon = 'fas fa-university';
                    break;
                case 'stripe_ideal':
                    icon = 'fas fa-university';
                    break;
                case 'stripe_becs':
                    icon = 'fas fa-university';
                    break;
                case 'paypalpro_payflow':
                    icon = 'far fa-credit-card';
                    break;
                case 'paypal-commerce':
                    icon = 'far fa-credit-card';
                    break;
                case 'stripe_google_pay':
                    icon = 'fab fa-google';
                    break;
                case 'stripe_apple_pay':
                    icon = 'fab fa-apple';
                    break;
                default:
                    icon = 'fas fa-hand-holding-heart';
                    break;
            }
            $(this).append(`<i class="${icon}"></i>`);
        });
    }

    /**
     * Setup prominent checkboxes (field api) (that use persistent borders on select)
     *
     * @since 2.14.0
     */
    function setupLegacyConsumerCheckboxAndRadio() {
        const customCheckboxes = document.querySelectorAll('[data-field-type="checkbox"] input');
        const customRadios = document.querySelectorAll('[data-field-type="radio"] input');
        Array.from(customCheckboxes).forEach((el) => {
            const uniqueInputSelector = `#${el.getAttribute('id')}`;
            const uniqueLabelSelector = `label[for=${el.getAttribute('id')}]`;
            setupCheckbox({
                container: uniqueLabelSelector,
                label: uniqueLabelSelector,
                input: uniqueInputSelector,
            });
        });

        Array.from(customRadios).forEach((el) => {
            const uniqueInputSelector = `#${el.getAttribute('id')}`;
            const uniqueLabelSelector = `label[for=${el.getAttribute('id')}]`;
            setupRadio({
                label: uniqueLabelSelector,
                input: uniqueInputSelector,
            });
        });
    }

    /**
     * Setup prominent checkboxes (that use persistent borders on select)
     *
     * @since 2.7.0
     * @since 2.15.0 update click handler callback
     * @param {object} args Argument object containing: container, label, input selectors
     */
    function setupCheckbox({container, label, input}) {
        // If checkbox is opted in by default, add border on load
        if ($(input).prop('checked') === true) {
            $(container).addClass('active');
        }

        // Persist checkbox input border when selected
        $(document).on('click', label, function (evt) {
            if ('INPUT' === evt.target.nodeName) {
                return;
            }

            $(container).toggleClass('active');
        });
    }

    /**
     * Handle updating label classes for FFM radios and checkboxes
     *
     * @since 2.7.0
     * @since 2.15.0 update click handler callback
     * @param {object} evt Reference to FFM input element click event
     */
    function setupRadio({label, input}) {
        // If checkbox is opted in by default, add border on load
        if ($(input).prop('checked') === true) {
            $(label).addClass('active');
        }

        // Persist checkbox input border when selected
        $(document).on('click', label, function (evt) {
            if ('INPUT' === evt.target.nodeName) {
                return;
            }

            $(evt.target.parentElement).find('label').not(evt.target).removeClass('active');
            $(evt.target).toggleClass('active');
        });
    }

    function setupHeightChangeCallback(callback) {
        let lastHeight = 0;
        function checkHeightChange() {
            const selector = $(steps[navigator.currentStep].selector);
            const changed = lastHeight !== $(selector).outerHeight();
            if (changed) {
                callback($(selector).outerHeight());
                lastHeight = $(selector).outerHeight();
            }
            window.requestAnimationFrame(checkHeightChange);
        }
        window.requestAnimationFrame(checkHeightChange);
    }

    /**
     * Get initial step to show donor.
     *
     * @since 2.7.0
     * @returns {number} Step to start on
     */
    function getInitialStep() {
        return Give.fn.getParameterByName('showDonationProcessingError') ||
            Give.fn.getParameterByName('showFailedDonationError')
            ? 2
            : 0;
    }

    function clearLoginNotices() {
        $('#give_error_must_log_in').remove();
    }

    /**
     * Setup select inputs
     *
     * @since 2.7.0
     */
    function setupSelectInputs() {
        if ($('select option[selected="selected"][value=""]').length > 0) {
            $('select option[selected="selected"][value=""]').each(function () {
                if ($(this).parent().siblings('label').length) {
                    $(this).text($(this).parent().siblings('label').text().replace('*', '').trim());
                    $(this).attr('disabled', true);
                }
            });
        }
    }

    /**
     * Check if document is RTL
     *
     * @since 2.8.0
     * @return {boolean} Whether or not document is RTL
     */
    function isRTL() {
        return $('html').attr('dir') === 'rtl';
    }

    /**
     * Scroll to parent window to iframe top
     *
     * @since 2.9.0
     */
    function scrollToIframeTop() {
        if ('parentIFrame' in window) {
            window.parentIFrame.sendMessage({action: 'giveScrollIframeInToView'});
        }
    }
})(jQuery);

/**
 * Support to FFM restore custom field value logic.
 *
 * FFM restore value of custom fields correctly but field state does not reflect correctly
 * in donation form because we are using custom styling for Radio and Checkbox.
 *
 * Below code will add class to Checkbox and Radio label if checked.
 *
 * @since 2.15.0
 */
document.addEventListener('readystatechange', function (evt) {
    if (evt.target.readyState !== 'complete') {
        return;
    }

    const customCheckboxes = document.querySelectorAll('[data-field-type="checkbox"] input');
    const customRadios = document.querySelectorAll('[data-field-type="radio"] input');

    const addActiveClass = (el) => {
        if (el.checked) {
            el.parentElement.classList.add('active');
        } else {
            el.parentElement.classList.remove('active');
        }
    };

    customCheckboxes.forEach(addActiveClass);
    customRadios.forEach(addActiveClass);
});
