(function($){
    'use strict';

    var languagesData    = window.wprTranslateLanguages || {};
    var stringsData      = window.wprTranslateStrings || {};
    var customFieldsData = window.wprTranslateCustomFields || {};
    var autoPostTypes    = window.wprTranslateAutoPostTypes || {};

    function initLanguagesManager() {
        var $wrapper = $('#wpr-languages-table');

        if ( ! $wrapper.length ) {
            return;
        }

        var $body           = $wrapper.find('.wpr-languages-body');
        var $noItems        = $wrapper.find('[data-role="empty-state"]');
        var $picker         = $('#wpr-language-picker');
        var $addButton      = $('#wpr-add-language-from-catalog');
        var template        = wp.template('wpr-language-row');
        var defaults        = languagesData.defaults || {};
        var strings         = languagesData.strings || {};
        var nextIndex       = parseInt( $wrapper.data('next-index'), 10 );
        var defaultDate     = $wrapper.data('default-date-format') || '';
        var defaultTime     = $wrapper.data('default-time-format') || '';

        if ( isNaN( nextIndex ) ) {
            nextIndex = $body.children('.wpr-language-row').length;
        }

        function refreshOrder() {
            $body.children('.wpr-language-row').each(function( position ){
                $( this ).find('.wpr-language-order-input').val( position );
            });
        }

        function refreshPickerState() {
            if ( ! $picker.length ) {
                return;
            }

            var disabledAll = true;

            $picker.find('option[value!=""]').each(function(){
                if ( ! $( this ).prop('disabled') ) {
                    disabledAll = false;
                    return false;
                }

                return true;
            });

            if ( $addButton.length ) {
                $addButton.prop( 'disabled', disabledAll );
            }
        }

        function toggleNoItemsRow() {
            if ( $body.children('.wpr-language-row').length ) {
                $noItems.hide();
            } else {
                $noItems.show();
            }
        }

        function updateRowCodeMetadata( $row, code ) {
            $row.attr( 'data-code', code );
            $row.find('.wpr-language-default-radio').val( code ).data( 'code', code );
            $row.find('.wpr-remove-language').attr( 'data-code', code );
        }

        function markDefault( code ) {
            var found = false;

            $body.find('.wpr-language-default-input').val( '0' );

            $body.children('.wpr-language-row').each(function(){
                var $row     = $( this );
                var rowCode  = $row.data( 'code' );
                var isMatch  = code && rowCode === code;

                if ( isMatch ) {
                    found = true;
                    $row.find('.wpr-language-default-input').val( '1' );
                    $row.find('.wpr-language-default-radio').prop( 'checked', true );
                    $row.find('input[name$="[is_active]"][type="checkbox"]').prop( 'checked', true );
                }
            });

            if ( ! found ) {
                var $first = $body.children('.wpr-language-row').first();

                if ( $first.length ) {
                    var firstCode = $first.data( 'code' );

                    $first.find('.wpr-language-default-input').val( '1' );
                    $first.find('.wpr-language-default-radio').prop( 'checked', true );
                    $first.find('input[name$="[is_active]"][type="checkbox"]').prop( 'checked', true );
                    updateRowCodeMetadata( $first, firstCode );
                }
            }
        }

        function addLanguageRow( data ) {
            var html = template( data );

            $noItems.hide();
            $body.append( html );
            refreshOrder();
            nextIndex++;
        }

        if ( $body.children('.wpr-language-row').length ) {
            $noItems.hide();
        }

        $body.sortable({
            handle: '.wpr-sort-handle',
            axis: 'y',
            items: '.wpr-language-row',
            placeholder: 'wpr-sort-placeholder',
            update: refreshOrder
        });

        $( document ).on( 'change', '.wpr-language-default-radio', function(){
            var code = $( this ).data( 'code' );
            markDefault( code );
        });

        $( document ).on( 'input', '.wpr-language-code-input', function(){
            var $input = $( this );
            var code   = $.trim( $input.val() );
            var $row   = $input.closest('.wpr-language-row');

            $input.removeClass( 'wpr-has-error' );
            updateRowCodeMetadata( $row, code );
        });

        $addButton.on( 'click', function(){
            if ( ! $picker.length ) {
                return;
            }

            var value = $picker.val();

            if ( ! value ) {
                return;
            }

            if ( $body.find('.wpr-language-row[data-code="' + value + '"]').length ) {
                if ( strings.duplicateLanguage ) {
                    window.alert( strings.duplicateLanguage );
                }
                $picker.val( '' );
                return;
            }

            var $option = $picker.find('option[value="' + value + '"]');
            var name    = $option.data( 'name' ) || '';

            if ( name ) {
                name = name.replace( /\s*\([^)]*\)\s*$/, '' );
            }

            var data    = {
                index: nextIndex,
                code: value,
                name: name,
                locale: $option.data( 'locale' ) || '',
                slug: $option.data( 'slug' ) || value,
                flag: $option.data( 'flag' ) || '',
                display_order: $body.children('.wpr-language-row').length,
                is_default: $body.children('.wpr-language-row').length ? '0' : '1',
                is_active: true,
                is_public: true,
                date_format: defaults.date_format || defaultDate || '',
                time_format: defaults.time_format || defaultTime || '',
                lock_code: true
            };

            addLanguageRow( data );
            updateRowCodeMetadata( $body.children('.wpr-language-row').last(), value );

            if ( '1' === data.is_default ) {
                markDefault( value );
            }

            $option.prop( 'disabled', true );
            $picker.val( '' );
            refreshPickerState();
        });

        $('#wpr-add-custom-language').on( 'click', function(){
            var isFirst = !$body.children('.wpr-language-row').length;
            var data    = {
                index: nextIndex,
                code: '',
                name: '',
                locale: '',
                slug: '',
                flag: '',
                display_order: $body.children('.wpr-language-row').length,
                is_default: isFirst ? '1' : '0',
                is_active: true,
                is_public: false,
                date_format: defaults.date_format || defaultDate || '',
                time_format: defaults.time_format || defaultTime || '',
                lock_code: false
            };

            addLanguageRow( data );

            var $newRow = $body.children('.wpr-language-row').last();
            updateRowCodeMetadata( $newRow, '' );

            if ( isFirst ) {
                markDefault( '' );
                $newRow.find('.wpr-language-default-input').val( '1' );
                $newRow.find('.wpr-language-default-radio').prop( 'checked', true );
            }
        });

        $( document ).on( 'click', '.wpr-remove-language', function(){
            var $row        = $( this ).closest('.wpr-language-row');
            var code        = $row.data( 'code' );
            var isDefault   = $row.find('.wpr-language-default-input').val() === '1';
            var rowCount    = $body.children('.wpr-language-row').length;

            if ( rowCount <= 1 ) {
                if ( strings.cannotRemoveLastLanguage ) {
                    window.alert( strings.cannotRemoveLastLanguage );
                }
                return;
            }

            $row.remove();
            refreshOrder();

            if ( $picker.length && code ) {
                var $option = $picker.find('option[value="' + code + '"]');
                if ( $option.length ) {
                    $option.prop( 'disabled', false );
                }
            }

            refreshPickerState();
            toggleNoItemsRow();

            if ( isDefault ) {
                var $firstRow = $body.children('.wpr-language-row').first();
                if ( $firstRow.length ) {
                    var nextCode = $firstRow.data( 'code' );
                    markDefault( nextCode );
                }
            } else {
                var $checked = $body.find('.wpr-language-default-radio:checked');
                if ( $checked.length ) {
                    markDefault( $checked.data( 'code' ) );
                }
            }
        });

        $('#wpr-languages-form').on( 'submit', function(){
            var valid = true;

            $body.find('.wpr-language-code-input').each(function(){
                var $input = $( this );
                if ( ! $.trim( $input.val() ) ) {
                    valid = false;
                    $input.addClass( 'wpr-has-error' );
                }
            });

            if ( ! valid ) {
                if ( strings.missingCode ) {
                    window.alert( strings.missingCode );
                }
                return false;
            }

            refreshOrder();

            var $checked = $body.find('.wpr-language-default-radio:checked');
            if ( $checked.length ) {
                markDefault( $checked.data( 'code' ) );
            }

            return true;
        });

        refreshPickerState();
        toggleNoItemsRow();
    }

    function initStringsInlineEditing() {
        var $inputs = $( '.wpr-translation-input' );

        if ( ! $inputs.length ) {
            return;
        }

        var ajaxUrl  = stringsData.ajaxUrl || '';
        var nonce    = stringsData.nonce || '';
        var messages = stringsData.messages || {};
        var delay    = parseInt( stringsData.saveDelay, 10 );

        if ( isNaN( delay ) || delay < 200 ) {
            delay = 2000;
        }

        if ( ! ajaxUrl || ! nonce ) {
            return;
        }

        $inputs.each( function(){
            var $input = $( this );
            $input.data( 'lastValue', $input.val() );
        } );

        function getErrorMessage( fallback, response ) {
            if ( response && response.data && response.data.message ) {
                return response.data.message;
            }

            return fallback;
        }

        function scheduleSave( $input, immediate ) {
            var timerId = $input.data( 'saveTimer' );

            if ( timerId ) {
                window.clearTimeout( timerId );
            }

            if ( immediate ) {
                saveTranslation( $input );
                return;
            }

            timerId = window.setTimeout( function(){
                saveTranslation( $input );
            }, delay );

            $input.data( 'saveTimer', timerId );
        }

        function saveTranslation( $input ) {
            var timerId = $input.data( 'saveTimer' );

            if ( timerId ) {
                window.clearTimeout( timerId );
                $input.removeData( 'saveTimer' );
            }

            if ( $input.data( 'saving' ) ) {
                scheduleSave( $input, false );
                return;
            }

            var currentValue = $input.val();
            var lastValue    = $input.data( 'lastValue' );

            if ( typeof lastValue !== 'undefined' && lastValue === currentValue ) {
                return;
            }

            var payload = {
                action: 'wpr_translate_save_translation',
                nonce: nonce,
                context: $input.data( 'context' ) || '',
                name: $input.data( 'name' ) || '',
                language: $input.data( 'language' ) || '',
                translation: currentValue
            };

            if ( ! payload.context || ! payload.name || ! payload.language ) {
                return;
            }

            $input.data( 'saving', true );
            $input.addClass( 'wpr-is-saving' );
            $input.prop( 'disabled', true );

            $.post( ajaxUrl, payload )
                .done( function( response ){
                    if ( response && response.success ) {
                        var savedValue = currentValue;

                        if ( response.data && typeof response.data.translation !== 'undefined' ) {
                            savedValue = response.data.translation;
                            $input.val( savedValue );
                        }

                        if ( response.data && response.data.status ) {
                            $input.closest('.wpr-cell-translation').attr( 'data-status', response.data.status );
                        }

                        $input.data( 'lastValue', savedValue );
                        $input.addClass( 'wpr-is-saved' );
                        $('.wpr-string-actions-note').removeClass( 'wpr-hidden' );

                        if ( messages.saved && window.wp && window.wp.a11y && window.wp.a11y.speak ) {
                            window.wp.a11y.speak( messages.saved, 'polite' );
                        }
                    } else {
                        var fallback = messages.error || 'Failed to save translation. Please try again.';
                        window.alert( getErrorMessage( fallback, response ) );
                        $input.addClass( 'wpr-has-error' );
                    }
                })
                .fail( function( jqXHR ){
                    var fallback = messages.error || 'Failed to save translation. Please try again.';
                    var response = jqXHR && jqXHR.responseJSON ? jqXHR.responseJSON : null;
                    window.alert( getErrorMessage( fallback, response ) );
                    $input.addClass( 'wpr-has-error' );
                })
                .always( function(){
                    $input.removeClass( 'wpr-is-saving' );
                    window.setTimeout( function(){
                        $input.removeClass( 'wpr-is-saved' );
                    }, 1500 );

                    window.setTimeout( function(){
                        $input.removeClass( 'wpr-has-error' );
                    }, 2000 );

                    $input.prop( 'disabled', false );
                    $input.data( 'saving', false );
                } );
        }

        $( document )
            .off( 'input.wprTranslate', '.wpr-card .wpr-translation-input' )
            .on( 'input.wprTranslate', '.wpr-card .wpr-translation-input', function(){
                scheduleSave( $( this ), false );
            } );

        $( document )
            .off( 'change.wprTranslate', '.wpr-card .wpr-translation-input' )
            .on( 'change.wprTranslate', '.wpr-card .wpr-translation-input', function(){
                scheduleSave( $( this ), false );
            } );

        $( document )
            .off( 'blur.wprTranslate', '.wpr-card .wpr-translation-input' )
            .on( 'blur.wprTranslate', '.wpr-card .wpr-translation-input', function(){
                scheduleSave( $( this ), true );
            } );
    }

    function initStringBulkSelection() {
        var $form = $('.wpr-string-bulk-form');

        if ( ! $form.length ) {
            return;
        }

        function setSelectAllState( checked ) {
            $form.find('.wpr-cell-select input[name="strings[]"]').prop( 'checked', checked );
        }

        $form.on( 'change', '#cb-select-all-1, #cb-select-all-2', function(){
            var isChecked = $( this ).prop( 'checked' );
            setSelectAllState( isChecked );
            $form.find('#cb-select-all-1, #cb-select-all-2').prop( 'checked', isChecked );
        } );

        $form.on( 'change', '.wpr-cell-select input[name="strings[]"]', function(){
            var $checkboxes = $form.find('.wpr-cell-select input[name="strings[]"]');
            var total       = $checkboxes.length;
            var checked     = $checkboxes.filter(':checked').length;
            var isAll       = total > 0 && checked === total;

            $form.find('#cb-select-all-1, #cb-select-all-2').prop( 'checked', isAll );
        } );
    }

    function initStringsAutoTranslate() {
        var settings = stringsData.autoTranslate || {};
        var ajaxUrl = settings.ajaxUrl || '';
        var nonce = settings.nonce || '';
        var action = settings.action || 'wpr_translate_auto_translate_strings';
        var labels = settings.strings || {};
        var $button = $( '#wpr-string-auto-translate-button' );
        var $domain = $( '#wpr-string-auto-translate-domain' );
        var $language = $( '#wpr-string-auto-translate-language' );
        var $status = $( '#wpr-string-auto-translate-status' );

        if ( ! $button.length || ! $language.length || ! ajaxUrl || ! nonce ) {
            return;
        }

        function setStatus( message ) {
            if ( $status.length ) {
                $status.text( message || '' );
            }
        }

        $button.on( 'click', function( event ) {
            var selectedLanguage;
            var selectedDomain;
            var totals = {
                processed: 0,
                updated: 0,
                inserted: 0,
                skipped: 0,
                errors: []
            };

            event.preventDefault();
            selectedLanguage = $.trim( $language.val() || '' );
            selectedDomain = $.trim( $domain.val() || '' );

            if ( ! selectedLanguage ) {
                setStatus( labels.missingLanguage || 'Please select a target language.' );
                return;
            }

            $button.prop( 'disabled', true );
            $button.attr( 'aria-busy', 'true' );
            setStatus( labels.running || 'Automatic translation is running...' );

            function runBatch( batchIndex ) {
                $.ajax( {
                    url: ajaxUrl,
                    method: 'POST',
                    dataType: 'json',
                    data: {
                        action: action,
                        nonce: nonce,
                        target_language: selectedLanguage,
                        target_domain: selectedDomain,
                        batch_index: batchIndex
                    }
                } )
                    .done( function( response ) {
                        var data;
                        var summary;

                        if ( ! response || ! response.success ) {
                            var message = labels.error || 'Automatic string translation failed. Please try again.';

                            if ( response && response.data && response.data.message ) {
                                message = response.data.message;
                            }

                            setStatus( message );
                            $button.prop( 'disabled', false );
                            $button.removeAttr( 'aria-busy' );
                            return;
                        }

                        data = response.data || {};
                        totals.processed += parseInt( data.processed_count || 0, 10 );
                        totals.updated += parseInt( data.updated_count || 0, 10 );
                        totals.inserted += parseInt( data.inserted_count || 0, 10 );
                        totals.skipped += parseInt( data.skipped_count || 0, 10 );

                        if ( data.errors && data.errors.length ) {
                            totals.errors = totals.errors.concat( data.errors );
                        }

                        if ( data.has_more ) {
                            setStatus(
                                ( labels.running || 'Automatic translation is running...' ) +
                                ' (batch ' + ( parseInt( data.batch_index || 0, 10 ) + 1 ) + '/' + ( data.batch_count || 1 ) + ')'
                            );
                            runBatch( parseInt( data.next_batch || 0, 10 ) );
                            return;
                        }

                        summary = ( labels.success || 'Automatic string translation completed.' ) +
                            ' processed: ' + totals.processed +
                            ', updated: ' + totals.updated +
                            ', inserted: ' + totals.inserted +
                            ', skipped: ' + totals.skipped;

                        if ( totals.errors.length ) {
                            summary += ' - errors: ' + totals.errors.length;
                        }

                        setStatus( summary );
                        $( '.wpr-string-actions-note' ).removeClass( 'wpr-hidden' );
                        $button.prop( 'disabled', false );
                        $button.removeAttr( 'aria-busy' );
                        window.location.reload();
                    } )
                    .fail( function( jqXHR ) {
                        var message = labels.error || 'Automatic string translation failed. Please try again.';

                        if ( jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.message ) {
                            message = jqXHR.responseJSON.data.message;
                        }

                        setStatus( message );
                        $button.prop( 'disabled', false );
                        $button.removeAttr( 'aria-busy' );
                    } );
            }

            runBatch( 0 );
        } );
    }

    function initCustomFieldRules() {
        var $rules = $( '.wpr-cf-rules' );

        if ( ! $rules.length ) {
            return;
        }

        var ajaxUrl  = customFieldsData.ajaxUrl || '';
        var nonce    = customFieldsData.nonce || '';
        var messages = customFieldsData.messages || {};

        if ( ! ajaxUrl || ! nonce ) {
            return;
        }

        $rules.on( 'click', '.wpr-cf-accordion-toggle', function(){
            var $toggle = $( this );
            var panelId = $toggle.attr( 'data-panel-id' );
            var $group;
            var $panel;
            var wasOpen;

            if ( ! panelId ) {
                return;
            }

            $group = $toggle.closest( '.wpr-cf-rules-group' );
            $panel = $group.find( '#' + panelId );

            if ( ! $panel.length ) {
                return;
            }

            wasOpen = $panel.hasClass( 'is-open' );

            $group.find( '.wpr-cf-accordion-panel' ).removeClass( 'is-open' );
            $group.find( '.wpr-cf-accordion-toggle' ).attr( 'aria-expanded', 'false' );

            if ( ! wasOpen ) {
                $panel.addClass( 'is-open' );
                $toggle.attr( 'aria-expanded', 'true' );
            }
        } );

        $rules.on( 'keydown', '.wpr-cf-accordion-toggle', function( event ){
            if ( 'Enter' === event.key || ' ' === event.key ) {
                event.preventDefault();
                $( this ).trigger( 'click' );
            }
        } );

        $rules.on( 'focus', '.wpr-cf-rule-select', function(){
            $( this ).data( 'previousValue', $( this ).val() );
        } );

        $rules.on( 'change', '.wpr-cf-rule-select', function(){
            var $select   = $( this );
            var ruleId    = $select.data( 'ruleId' ) || '';
            var value     = $select.val() || '';
            var $row      = $select.closest( '.wpr-cf-rule-row' );
            var $status   = $row.find( '.wpr-cf-rule-status' );
            var previous  = $select.data( 'previousValue' );

            if ( ! ruleId || ! value ) {
                return;
            }

            $select.prop( 'disabled', true );

            if ( $status.length && messages.saving ) {
                $status.text( messages.saving );
            }

            $.post( ajaxUrl, {
                action: 'wpr_translate_save_cf_rule',
                nonce: nonce,
                rule: ruleId,
                value: value
            } )
                .done( function( response ){
                    if ( response && response.success ) {
                        var data   = response.data || {};
                        var source = data.source || 'file';
                        var text   = '';

                        if ( data.action ) {
                            $select.val( data.action );
                        }

                        if ( 'override' === source ) {
                            $row.addClass( 'has-override' );
                            text = messages.saved || data.message || '';
                        } else {
                            $row.removeClass( 'has-override' );
                            text = messages.reverted || data.message || '';
                        }

                        if ( data.message && ! text ) {
                            text = data.message;
                        }

                        if ( $status.length ) {
                            $status.text( text );
                        }

                        $row.attr( 'data-rule-source', source );
                        $select.data( 'previousValue', $select.val() );

                        var announcement = text;
                        if ( ! announcement && messages.saved ) {
                            announcement = messages.saved;
                        }

                        if ( announcement && window.wp && window.wp.a11y && window.wp.a11y.speak ) {
                            window.wp.a11y.speak( announcement, 'polite' );
                        }
                    } else {
                        var fallback = messages.error || 'Failed to save action. Please try again.';

                        if ( response && response.data && response.data.message ) {
                            fallback = response.data.message;
                        }

                        window.alert( fallback );

                        if ( typeof previous !== 'undefined' ) {
                            $select.val( previous );
                        }

                        if ( $status.length ) {
                            $status.text( '' );
                        }
                    }
                } )
                .fail( function( jqXHR ){
                    var fallback = messages.error || 'Failed to save action. Please try again.';
                    var response = jqXHR && jqXHR.responseJSON ? jqXHR.responseJSON : null;

                    if ( response && response.data && response.data.message ) {
                        fallback = response.data.message;
                    }

                    window.alert( fallback );

                    if ( typeof previous !== 'undefined' ) {
                        $select.val( previous );
                    }

                    if ( $status.length ) {
                        $status.text( '' );
                    }
                } )
                .always( function(){
                    $select.prop( 'disabled', false );

                    if ( $status.length ) {
                        window.setTimeout( function(){
                            $status.text( '' );
                        }, 2000 );
                    }
                } );
        } );
    }

    function initPostEditorAutoTranslate() {
        var settings = window.wprTranslateAutoSettings || {};
        var defaultProcessing = 'Doing the translation. Please wait....';

        $( document ).on( 'click', '.wpr-translate-auto-translate-button', function( event ) {
            var $button = $( this );
            var postId;
            var sourcePostId;
            var requestData;
            var language;
            var originalLabel;
            var processingLabel;
            var defaultError;

            event.preventDefault();

            postId = parseInt( $button.data( 'post-id' ), 10 );
            sourcePostId = parseInt( $button.data( 'source-post-id' ), 10 );

            if ( ! postId || ! settings.ajax || ! settings.ajax.url || ! settings.ajax.nonce ) {
                return;
            }

            language        = $button.data( 'language' ) || '';
            originalLabel   = $button.data( 'original-label' ) || $.trim( $button.text() );
            processingLabel = settings.strings && settings.strings.processing ? settings.strings.processing : defaultProcessing;
            defaultError    = settings.strings && settings.strings.error ? settings.strings.error : 'Automatic translation failed. Please try again.';

            $button.prop( 'disabled', true );
            $button.attr( 'aria-busy', 'true' );
            $button.text( processingLabel );

            requestData = {
                action: 'wpr_translate_auto_translate_post',
                nonce: settings.ajax.nonce,
                post_id: postId
            };

            if ( sourcePostId > 0 ) {
                requestData.source_post_id = sourcePostId;
            }

            if ( language ) {
                requestData.language = language;
            }

            $.ajax( {
                url: settings.ajax.url,
                method: 'POST',
                dataType: 'json',
                data: requestData
            } )
                .done( function( response ) {
                    if ( ! response || ! response.success ) {
                        var message = response && response.data && response.data.message ? response.data.message : defaultError;

                        window.alert( message );
                        return;
                    }

                    window.location.reload();
                } )
                .fail( function( jqXHR ) {
                    var fallback = defaultError;

                    if ( jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.message ) {
                        fallback = jqXHR.responseJSON.data.message;
                    }

                    window.alert( fallback );
                } )
                .always( function() {
                    $button.prop( 'disabled', false );
                    $button.removeAttr( 'aria-busy' );
                    $button.text( originalLabel );
                } );
        } );
    }

    function initAutoTranslationPostTypes() {
        var settings        = autoPostTypes || {};
        var $container      = $('.wpr-auto-translation-post-types');
        var $languageSelect = $('#wpr-auto-translation-language');

        if ( ! $container.length || ! settings.ajax || ! settings.ajax.url || ! settings.ajax.nonce ) {
            return;
        }

        var $button      = $container.find('.wpr-start-translation');
        var defaultLabel = $.trim( $button.data( 'label' ) || $button.text() );
        var savingLabel  = settings.strings && settings.strings.saving ? settings.strings.saving : defaultLabel;
        var errorMessage = settings.strings && settings.strings.error ? settings.strings.error : '';
        var saving       = false;

        if ( ! $button.length ) {
            return;
        }

        // Build a map of post type preferences based on the current radio selections.
        function collectPostTypes() {
            var postTypes = {};

            $container.find('.wpr-post-type-row').each(function(){
                var $row       = $( this );
                var postType   = $row.data( 'post-type' ) || '';
                var selection  = $row.find('input[type="radio"]:checked').val();
                var preference = 'yes' === selection ? 'yes' : 'no';

                if ( postType ) {
                    postTypes[ postType ] = preference;
                }
            });

            return postTypes;
        }

        function getSelectedLanguage() {
            if ( ! $languageSelect.length ) {
                return '';
            }

            return $.trim( $languageSelect.val() || '' );
        }

        // Save the current preferences via AJAX so selections persist immediately.
        function savePreferences() {
            if ( $container.data( 'wprAutoProcessing' ) ) {
                return;
            }
            var postTypes = collectPostTypes();

            if ( saving ) {
                return;
            }

            saving = true;
            $button.prop( 'disabled', true );
            $button.attr( 'aria-busy', 'true' );
            $button.text( savingLabel );

            $.ajax({
                url: settings.ajax.url,
                method: 'POST',
                dataType: 'json',
                data: {
                    action: 'wpr_translate_save_post_type_preferences',
                    nonce: settings.ajax.nonce,
                    post_types: postTypes,
                    target_language: getSelectedLanguage()
                }
            }).fail(function( jqXHR ){
                var message = errorMessage;

                if ( jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.message ) {
                    message = jqXHR.responseJSON.data.message;
                }

                if ( message ) {
                    window.alert( message );
                }
            }).always(function(){
                $button.prop( 'disabled', false );
                $button.removeAttr( 'aria-busy' );
                $button.text( defaultLabel );
                saving = false;
            });
        }

        $container.on( 'change', 'input[type="radio"]', function(){
            savePreferences();
        });

        $languageSelect.on( 'change', function(){
            savePreferences();
        });
    }

    function initAutoTranslationRunner() {
        var settings    = autoPostTypes || {};
        var $container  = $('.wpr-auto-translation-post-types');
        var translation = settings.translation || {};
        var ajax        = settings.ajax || {};
        var $button     = $container.find('.wpr-start-translation');
        var $stopButton = $container.find('.wpr-stop-translation');
        var $languageSelect = $('#wpr-auto-translation-language');
        var $status     = $('#wpr_translate_auto_status_update');
        var postsNonce  = settings.postsNonce || '';
        var defaultLabel = $.trim( $button.data( 'label' ) || $button.text() );
        var runningLabel = settings.strings && settings.strings.running ? settings.strings.running : defaultLabel;
        var savingLabel  = settings.strings && settings.strings.saving ? settings.strings.saving : defaultLabel;
        var errorMessage = settings.strings && settings.strings.translationError ? settings.strings.translationError : '';
        var preparingLabel = settings.strings && settings.strings.preparing ? settings.strings.preparing : '';
        var completeLabel  = settings.strings && settings.strings.complete ? settings.strings.complete : '';
        var noneFoundLabel = settings.strings && settings.strings.noPosts ? settings.strings.noPosts : '';
        var stoppedLabel  = settings.strings && settings.strings.stopped ? settings.strings.stopped : '';
        var processing   = false;
        var saving       = false;
        var stopRequested = false;
        var currentRequest = null;

        if ( ! $container.length || ! $button.length || ! ajax.url || ! ajax.nonce || ! translation.nonce ) {
            return;
        }

        if ( $stopButton.length ) {
            $stopButton.prop( 'disabled', true );
        }

        function setStatus( message ) {
            if ( $status.length ) {
                $status.text( message || '' );
            }
        }

        function collectPostTypes() {
            var postTypes = {};

            $container.find('.wpr-post-type-row').each(function(){
                var $row       = $( this );
                var postType   = $row.data( 'post-type' ) || '';
                var selection  = $row.find('input[type="radio"]:checked').val();
                var preference = 'yes' === selection ? 'yes' : 'no';

                if ( postType ) {
                    postTypes[ postType ] = preference;
                }
            });

            return postTypes;
        }

        function getSelectedLanguage() {
            if ( ! $languageSelect.length ) {
                return translation.language || '';
            }

            return $.trim( $languageSelect.val() || '' );
        }

        function savePreferences() {
            var postTypes = collectPostTypes();
            var deferred  = $.Deferred();
            var isRun     = processing;

            if ( saving ) {
                deferred.resolve();
                return deferred.promise();
            }

            saving = true;
            if ( ! isRun ) {
                $button.prop( 'disabled', true );
                $button.attr( 'aria-busy', 'true' );
                $button.text( savingLabel );
            }

            $.ajax({
                url: ajax.url,
                method: 'POST',
                dataType: 'json',
                data: {
                    action: 'wpr_translate_save_post_type_preferences',
                    nonce: ajax.nonce,
                    post_types: postTypes,
                    target_language: getSelectedLanguage()
                }
            }).done(function(){
                deferred.resolve();
            }).fail(function( jqXHR ){
                var message = errorMessage;

                if ( jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.message ) {
                    message = jqXHR.responseJSON.data.message;
                }

                deferred.reject( message );
            }).always(function(){
                if ( ! isRun ) {
                    $button.prop( 'disabled', false );
                    $button.removeAttr( 'aria-busy' );
                    $button.text( defaultLabel );
                }
                saving = false;
            });

            return deferred.promise();
        }

        function fetchPostsForTranslation( postTypes, batchIndex ) {
            currentRequest = $.ajax({
                url: ajax.url,
                method: 'POST',
                dataType: 'json',
                data: {
                    action: 'wpr_translate_get_posts_for_auto_translation',
                    nonce: postsNonce,
                    post_types: postTypes,
                    target_language: getSelectedLanguage(),
                    batch_index: batchIndex
                }
            });

            return currentRequest;
        }

        function translatePost( post ) {
            var actionName = translation.action ? translation.action : 'wpr_translate_auto_translate_post_publish';
            var requestData = {
                action: actionName,
                nonce: translation.publishNonce ? translation.publishNonce : translation.nonce,
                post_id: post.id
            };

            if ( post.source_post_id ) {
                requestData.source_post_id = post.source_post_id;
            }

            if ( translation.language ) {
                requestData.language = translation.language;
            }

            currentRequest = $.ajax({
                url: translation.ajax || ajax.url,
                method: 'POST',
                dataType: 'json',
                data: requestData
            });

            return currentRequest;
        }

        function finishProcessing( message ) {
            processing = false;
            $container.data( 'wprAutoProcessing', false );
            $button.prop( 'disabled', false );
            $button.removeAttr( 'aria-busy' );
            $button.text( defaultLabel );
            if ( $stopButton.length ) {
                $stopButton.prop( 'disabled', true );
                $stopButton.removeAttr( 'aria-busy' );
            }
            currentRequest = null;
            setStatus( message || '' );
        }

        function processQueue( posts, index, attempt, summary, onComplete ) {
            if ( index >= posts.length ) {
                if ( typeof onComplete === 'function' ) {
                    onComplete( summary );
                }
                return;
            }

            var currentAttempt = attempt || 1;
            var post           = posts[ index ] || {};
            var postId         = post.id || '';
            var postTitle      = $.trim( post.title || '' );
            var attemptLabel   = currentAttempt > 1 ? ' (attempt ' + currentAttempt + ' of 3)' : '';
            var statusMessage  = 'we are updating post id ' + postId + ' - ' + postTitle + attemptLabel;

            setStatus( statusMessage );

            if ( stopRequested ) {
                finishProcessing( stoppedLabel );
                return;
            }

            translatePost( post )
                .done( function( response ) {
                    currentRequest = null;

                    if ( stopRequested ) {
                        finishProcessing( stoppedLabel );
                        return;
                    }

                    if ( ! response || ! response.success ) {
                        var message = errorMessage;

                        if ( response && response.data && response.data.message ) {
                            message = response.data.message;
                        }

                        if ( currentAttempt < 3 ) {
                            window.setTimeout( function(){
                                processQueue( posts, index, currentAttempt + 1, summary, onComplete );
                            }, 1000 );
                            return;
                        }

                        summary.failed += 1;
                        setStatus( message );
                        window.setTimeout( function(){
                            processQueue( posts, index + 1, 1, summary, onComplete );
                        }, 1000 );
                        return;
                    }

                    summary.translated += 1;
                    window.setTimeout( function(){
                        processQueue( posts, index + 1, 1, summary, onComplete );
                    }, 1000 );
                } )
                .fail( function( jqXHR ) {
                    var message = errorMessage;

                    currentRequest = null;

                    if ( stopRequested ) {
                        finishProcessing( stoppedLabel );
                        return;
                    }

                    if ( jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.message ) {
                        message = jqXHR.responseJSON.data.message;
                    }

                    if ( currentAttempt < 3 ) {
                        window.setTimeout( function(){
                            processQueue( posts, index, currentAttempt + 1, summary, onComplete );
                        }, 1000 );
                        return;
                    }

                    summary.failed += 1;
                    setStatus( message );
                    window.setTimeout( function(){
                        processQueue( posts, index + 1, 1, summary, onComplete );
                    }, 1000 );
                } );
        }

        function buildRunSummary( totals ) {
            var summary = completeLabel ? completeLabel : 'Automatic translation completed.';
            summary += ' translated: ' + totals.translated + ', failed: ' + totals.failed + ', draft errors: ' + totals.draftErrors;

            return summary;
        }

        function startTranslation() {
            if ( processing ) {
                return;
            }

            stopRequested = false;
            translation.language = getSelectedLanguage();
            processing = true;
            $container.data( 'wprAutoProcessing', true );
            $button.prop( 'disabled', true );
            $button.attr( 'aria-busy', 'true' );
            $button.text( runningLabel );
            if ( $stopButton.length ) {
                $stopButton.prop( 'disabled', false );
            }
            setStatus( preparingLabel );

            savePreferences()
                .done( function(){
                    if ( stopRequested ) {
                        finishProcessing( stoppedLabel );
                        return;
                    }

                    var postTypes = collectPostTypes();
                    var totals = {
                        translated: 0,
                        failed: 0,
                        draftErrors: 0,
                        sourceCount: 0
                    };

                    function runBatch( batchIndex ) {
                        var humanBatchIndex = parseInt( batchIndex || 0, 10 ) + 1;
                        var preparingMessage = preparingLabel ? preparingLabel : 'Collecting posts to translate...';

                        if ( stopRequested ) {
                            finishProcessing( stoppedLabel );
                            return;
                        }

                        setStatus( preparingMessage + ' (batch ' + humanBatchIndex + ')' );

                        fetchPostsForTranslation( postTypes, batchIndex )
                            .done( function( response ) {
                                var message = errorMessage;
                                var data;
                                var posts;
                                var hasMore;
                                var nextBatch;
                                var sourceCount;
                                var batchSummary;

                                if ( stopRequested ) {
                                    finishProcessing( stoppedLabel );
                                    return;
                                }

                                if ( ! response || ! response.success || ! response.data || ! $.isArray( response.data.posts ) ) {
                                    if ( response && response.data && response.data.message ) {
                                        message = response.data.message;
                                    }

                                    finishProcessing( message );
                                    return;
                                }

                                data = response.data || {};
                                posts = data.posts || [];
                                hasMore = !! data.has_more;
                                nextBatch = parseInt( data.next_batch || ( parseInt( batchIndex, 10 ) + 1 ), 10 );
                                sourceCount = parseInt( data.source_count || 0, 10 );
                                totals.sourceCount += sourceCount;
                                totals.draftErrors += parseInt( data.draft_error_count || 0, 10 );
                                currentRequest = null;

                                if ( ! posts.length ) {
                                    if ( hasMore ) {
                                        runBatch( nextBatch );
                                        return;
                                    }

                                    if ( 0 === totals.sourceCount && 0 === totals.draftErrors ) {
                                        finishProcessing( noneFoundLabel );
                                        return;
                                    }

                                    finishProcessing( buildRunSummary( totals ) );
                                    return;
                                }

                                batchSummary = {
                                    translated: 0,
                                    failed: 0
                                };

                                processQueue(
                                    posts,
                                    0,
                                    1,
                                    batchSummary,
                                    function( completedSummary ) {
                                        totals.translated += parseInt( completedSummary.translated || 0, 10 );
                                        totals.failed += parseInt( completedSummary.failed || 0, 10 );

                                        if ( stopRequested ) {
                                            finishProcessing( stoppedLabel );
                                            return;
                                        }

                                        if ( hasMore ) {
                                            runBatch( nextBatch );
                                            return;
                                        }

                                        finishProcessing( buildRunSummary( totals ) );
                                    }
                                );
                            } )
                            .fail( function( jqXHR ) {
                                var message = errorMessage;

                                currentRequest = null;

                                if ( stopRequested ) {
                                    finishProcessing( stoppedLabel );
                                    return;
                                }

                                if ( jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.message ) {
                                    message = jqXHR.responseJSON.data.message;
                                }

                                finishProcessing( message );
                            } );
                    }

                    runBatch( 0 );
                } )
                .fail( function( message ) {
                    finishProcessing( message || errorMessage );
                } );
        }

        $button.on( 'click', function( event ) {
            event.preventDefault();
            startTranslation();
        });

        $stopButton.on( 'click', function( event ) {
            event.preventDefault();

            if ( ! processing ) {
                return;
            }

            stopRequested = true;

            if ( currentRequest && currentRequest.abort ) {
                currentRequest.abort();
            }

            finishProcessing( stoppedLabel );
        });
    }

    function initPostEditorLanguageBadge() {
        // Render the current post language badge inside the block editor header.
        var data = window.wprTranslatePostLanguage || {};
        var attempts = 0;
        var maxAttempts = 20;

        function findHeader() {
            return document.querySelector(
                '.editor-header__settings, .edit-post-header__settings, .edit-post-header__toolbar'
            );
        }

        function mountBadge() {
            var headerSettings = findHeader();

            if ( ! headerSettings ) {
                attempts += 1;
                if ( attempts <= maxAttempts ) {
                    window.setTimeout( mountBadge, 300 );
                }
                return;
            }

            if ( ! data || ! data.label ) {
                return;
            }

            if ( headerSettings.querySelector( '.wpr-editor-language-badge' ) ) {
                return;
            }

            var badge = document.createElement( 'div' );
            badge.className = 'wpr-editor-language-badge';
            badge.setAttribute( 'title', data.code ? String( data.code ).toUpperCase() : data.label );

            var flag = document.createElement( 'div' );
            flag.className = 'wpr-editor-language-flag';

            if ( data.flagUrl ) {
                flag.style.backgroundImage = 'url(' + data.flagUrl + ')';
                flag.setAttribute( 'role', 'img' );
                flag.setAttribute( 'aria-label', data.flagAlt || data.label );
            } else {
                flag.classList.add( 'wpr-editor-language-flag--empty' );
            }

            var label = document.createElement( 'div' );
            label.className = 'wpr-editor-language-label';
            label.textContent = data.label;

            badge.appendChild( flag );
            badge.appendChild( label );
            headerSettings.insertBefore( badge, headerSettings.firstChild );
        }

        mountBadge();
    }

    $( function(){
        initLanguagesManager();
        initStringsInlineEditing();
        initStringBulkSelection();
        initStringsAutoTranslate();
        initCustomFieldRules();
        initPostEditorAutoTranslate();
        initPostEditorLanguageBadge();
        initAutoTranslationPostTypes();
        initAutoTranslationRunner();
    });

    $( document ).on( 'click', '[data-wpr-toggle]', function(){
        var target = $( this ).data( 'wpr-toggle' );
        $( target ).toggleClass( 'is-open' );
    });
})(jQuery);
