// source --> https://www.s-techworks.at/wp-content/plugins/translatepress-developer/add-ons-pro/automatic-language-detection/assets/js/trp-language-cookie.js?ver=1.1.1 
/**
 * Sets proper language cookie
 *
 * Sends ajax request to get browser and IP language.
 * Sets cookie with current language.
 * Changes cookie when clicking a link pointed to another language.
 *
 */
function TRP_IN_Determine_Language(){
    var _this = this;
    var trpCookie = null;
    var trpHelper = null;

    this.get_lang_from_url = function ( url ) {
        // Check domain mappings first if Multiple Domains is active
        if ( trp_language_cookie_data['domain_language_map'] ) {
            var domainLang = _this.get_lang_from_domain( url );
            if ( domainLang ) {
                return domainLang;
            }
        }

        // Fall back to path-based detection
        // we remove http or https
        // if the user links to a http link but the abs_home_url is https, we're serving the https one so we don't brake cookies if he doesn't have proper redirects
        var lang = url.replace( /^(http|https):\/\//g, '');
        var abs_home = trp_language_cookie_data[ 'abs_home' ].replace( /^(http|https):\/\//g, '');

        // we have removed the home path from our URL. We're adding a / in case it's the homepage of one of the languages
        // removing / from the front so it's easier for understanding explode()
        lang = trpHelper.ltrim( trpHelper.trailingslashit( lang.replace(abs_home, '') ),'/' );

        // We now have to see if the first part of the string is actually a language slug
        var lang_array = lang.split("/");
        if( lang_array.length < 2 ){
            return trp_language_cookie_data['default_language'];
        }
        // The language code is the first non-empty item in this array depending on abs_home slashes
        for ( var i = 0; i < lang_array.length; i++ ){
            if ( lang_array[i] != undefined && lang_array[i] != '' ) {
                lang = lang_array[i];
                break;
            }
        }
        // the lang slug != actual lang. So we need to do array_search so we don't end up with en instead of en_US
        if( trpHelper.in_array( lang, trp_language_cookie_data['url_slugs']) ){
            return trpHelper.array_search(lang, trp_language_cookie_data['url_slugs'] );
        } else {
            return trp_language_cookie_data['default_language'];
        }

    };

    /**
     * Extract language from URL's domain using domain_language_map
     * Used when Multiple Domains addon is active
     *
     * @param {string} url - URL to extract domain from
     * @return {string|null} Language code or null if not found
     */
    this.get_lang_from_domain = function( url ) {
        var domainMap = trp_language_cookie_data['domain_language_map'];
        if ( !domainMap ) {
            return null;
        }

        // Extract hostname from URL
        var hostname;
        try {
            var urlObj = new URL( url );
            hostname = urlObj.hostname;
        } catch ( e ) {
            // Fallback for older browsers or malformed URLs
            var match = url.match( /^(?:https?:\/\/)?([^\/]+)/i );
            hostname = match ? match[1] : null;
        }

        if ( !hostname ) {
            return null;
        }

        // Check if hostname matches any configured domain
        if ( domainMap[hostname] ) {
            return domainMap[hostname];
        }

        return null;
    };

    this.get_current_dom_language = function(){
        var html_language_document = document.getElementById("tp-language");
        var html_language;
        if ( html_language_document ){
            if ( jQuery('#tp-language').attr('data-tp-language') ){
                html_language = jQuery( '#tp-language' ).attr( 'data-tp-language' );
            }else if (jQuery('#tp-language').attr('lang') ){
                html_language = jQuery( '#tp-language' ).attr( 'lang' );
            }
        } else {
            html_language = jQuery('html').attr('lang');
            html_language = html_language.split("-").join("_");
        }

        if ( !trpHelper.in_array( html_language, trp_language_cookie_data['publish_languages'] ) ){
            html_language = "error_determining_language";
        }

        return html_language;
    };


    this.ajax_get_needed_language = function() {
        jQuery.ajax({
            url: trp_language_cookie_data['trp_ald_ajax_url'],
            type: 'post',
            dataType: 'json',
            data: {
                action: 'trp_ald_get_needed_language',
                detection_method: trp_language_cookie_data['detection_method'],
                popup_option: trp_language_cookie_data['popup_option'],
                popup_textarea: trp_language_cookie_data['popup_textarea'],
                popup_type: trp_language_cookie_data['popup_type'],
                popup_textarea_change_button: trp_language_cookie_data['popup_textarea_change_button'],
                popup_textarea_close_button: trp_language_cookie_data['popup_textarea_close_button'],
                publish_languages: trp_language_cookie_data['publish_languages'],
                iso_codes: trp_language_cookie_data['iso_codes'],
                english_name: trp_language_cookie_data['english_name'],
                default_language: trp_language_cookie_data['default_language'],
                is_iphone_user_check: trp_language_cookie_data['is_iphone_user_check']
            },
            success: function( response ) {
                if ( response ) {
                    _this.redirect_if_needed( response );
                }else{
                    _this.redirect_if_needed( _this.get_current_dom_language() );
                }

            },
            error: function( errorThrown ){
                // make current language the needed language
                _this.redirect_if_needed( _this.get_current_dom_language() );
            }
        });
    };

    this.activate_popup = function( response, url_to_redirect ){

        _this.make_ls_clickable();
        _this.ls_make_default_language_preselected( response );

        var popup = document.getElementById("trp_ald_modal_container");
        var close = document.getElementById("trp_ald_x_button");
        var popup_change_button = document.getElementById("trp_ald_popup_change_language");
        var close_popup = document.getElementById("trp_ald_x_button_and_textarea");
        var no_text_popup_select_current_language = document.querySelector('[special-selector = "trp_ald_popup_current_language"]');

        popup.style.display = 'block';

        close_popup.onclick = function(e){
            popup.style.display = 'none';
            trpCookie.setCookie( trp_language_cookie_data['cookie_name'], _this.get_current_dom_language(), trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );

            // Anchor looks like this <a href="#">. This prevents navigating to #
            e.preventDefault();
        }

        _this.ls_select_language();

        popup_change_button.onclick = function(){
            var selected_language = no_text_popup_select_current_language.getAttribute('data-trp-ald-selected-language');
            trpCookie.setCookie( trp_language_cookie_data['cookie_name'], selected_language, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );
        }
    }


    this.activate_hello_bar = function (response, url_to_redirect){

        var no_text_popup = document.getElementById("trp_ald_no_text_popup_template");
        var clone = no_text_popup.content.cloneNode(true);

        var close_button = clone.getElementById('trp_close');
        var button_change_language_no_text_popup = clone.getElementById('trp_ald_no_text_popup_change_language');
        var no_text_popup_select_current_language = clone.querySelector('[special-selector = "trp_ald_popup_current_language"]');

        var div = document.createElement('div');
        div.appendChild(clone);
        document.body.insertAdjacentElement('afterbegin', div);

        button_change_language_no_text_popup.onclick = function() {
            var selected_language = no_text_popup_select_current_language.getAttribute( 'data-trp-ald-selected-language' );
            trpCookie.setCookie( trp_language_cookie_data[ 'cookie_name' ], selected_language, trp_language_cookie_data[ 'cookie_age' ], trp_language_cookie_data[ 'cookie_path' ] );
        }

        var remove_bar = function () {
            trpCookie.setCookie( trp_language_cookie_data['cookie_name'], _this.get_current_dom_language(), trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );
            document.body.removeChild(div);
        };

        close_button.onclick = remove_bar;

        _this.make_ls_clickable();
        _this.ls_select_language();
        _this.ls_make_default_language_preselected( response );
    }


    this.make_ls_clickable = function (){
        jQuery('.trp_ald_ls_container .trp-ls-shortcode-current-language').click(function () {
            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).addClass('trp-ls-clicked');
            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).addClass('trp-ls-clicked');
        });

        jQuery('.trp_ald_ls_container .trp-ls-shortcode-language').click(function () {
            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).removeClass('trp-ls-clicked');
            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).removeClass('trp-ls-clicked');
        });


        jQuery(document).keyup(function(e) {
            if (e.key === "Escape") {
                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).removeClass('trp-ls-clicked');
                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).removeClass('trp-ls-clicked');
            }
        });

        jQuery(document).on("click", function(event){
            if(!jQuery(event.target).closest(".trp_ald_ls_container .trp-ls-shortcode-current-language").length){
                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).removeClass('trp-ls-clicked');
                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).removeClass('trp-ls-clicked');
            }
        });
    }

    this.ls_select_language = function(){
        
        var no_text_current_language = document.querySelector('.trp_ald_ls_container .trp-ls-shortcode-current-language');
        var no_text_popup_select_current_language = document.querySelector('.trp_ald_ls_container .trp-ls-shortcode-current-language');
        var popup_change_button = document.getElementById("trp_ald_popup_change_language");
        var button_change_language_no_text_popup = document.getElementById('trp_ald_no_text_popup_change_language');
        jQuery('.trp-ald-popup-select').click(function ( item ) {
            no_text_current_language.innerHTML = item.target.innerHTML;
            no_text_current_language.setAttribute('data-trp-ald-selected-language', item.target.getAttribute('data-trp-ald-selected-language'));
            var selected_language = no_text_popup_select_current_language.getAttribute('data-trp-ald-selected-language');
            _this.set_language_href(selected_language,popup_change_button,button_change_language_no_text_popup);
        });
    }

    this.ls_make_default_language_preselected = function( response ){

        var no_text_current_language = document.querySelector('[special-selector = "trp_ald_popup_current_language"]');
        var all_languages = document.querySelectorAll('.trp_ald_ls_container .trp-ald-popup-select');
        var popup_change_button = document.getElementById("trp_ald_popup_change_language");
        var button_change_language_no_text_popup = document.getElementById('trp_ald_no_text_popup_change_language');
        for ( var i = 0; i< all_languages.length; i++){
            if (all_languages[i].id === response){
                no_text_current_language.innerHTML = all_languages[i].innerHTML;
                no_text_current_language.setAttribute('data-trp-ald-selected-language', response);
                no_text_current_language.setAttribute('id', response);
                var selected_language = no_text_current_language.getAttribute('data-trp-ald-selected-language');
                _this.set_language_href(selected_language, popup_change_button, button_change_language_no_text_popup);
                break;
            }
        }
    }

    this.set_language_href = function ( selected_language, popup_change_button, button_change_language_no_text_popup ){
        if( popup_change_button !== null ){
            popup_change_button.href = _this.get_url_for_lang(selected_language);
        }
        if( button_change_language_no_text_popup !== null ){
            button_change_language_no_text_popup.href = _this.get_url_for_lang(selected_language);
        }
    }

    this.decode_HTML_entities = function(str) {
        let txt = new DOMParser().parseFromString(str, "text/html");
        return txt.documentElement.textContent;
    }

    this.get_url_for_lang = function( language ){

        for( i in trp_language_cookie_data['language_urls'] ){
            if( i === language ) {
                let url_for_language = _this.decode_HTML_entities(trp_language_cookie_data['language_urls'][i]);

                return url_for_language;
            }
        }
        return false;
    };

    this.is_valid_url = function ( url ) {
        if ( typeof url === 'undefined' || url === '' ){
            return false;
        }
        var starting_characters = ['#','?', 'javascript'];
        for (var i = 0; i < starting_characters.length; i++ ){
            if ( url.substring(0, starting_characters[i].length) === starting_characters[i]){
                return false;
            }
        }
        return true;
    };

    this.replace_underscore_with_dash = function (var_replace){
        var_replace = var_replace.toLowerCase();
        var_replace = var_replace.split("_").join("-");

        return var_replace;
    }

    this.is_same_language_code = function (var1, var2){
        var1 = _this.replace_underscore_with_dash(var1);
        var2 = _this.replace_underscore_with_dash(var2);

        if( var1 == var2 || var1 == "error_determining_language" || var2 == "error_determining_language" ){
            return true;
        }
        return false;
    }

    this.is_login_url = function( url ){
        if( url.includes( "wp-login.php" )){
            return true;
        }
        return false;
    }

    this.add_event_handlers = function(){
        jQuery('body').on('click', 'a', function(e) {

            var clicked_url = jQuery(this).attr("href");
            if ( _this.is_valid_url( clicked_url ) && !_this.is_login_url( clicked_url )) {
                var clicked_language = _this.get_lang_from_url(clicked_url);
                var trp_current_language = trpCookie.getCookie(trp_language_cookie_data['cookie_name']);

                if (!(_this.is_same_language_code(trp_current_language, clicked_language))) {
                    // When Multiple Domains is active, only handle clicks to our configured domains
                    if ( trp_language_cookie_data['domain_language_map'] && !_this.get_lang_from_domain( clicked_url ) ) {
                        return; // External URL — don't change cookie or add trp_lang_switch
                    }

                    // Skip cross-domain sync here — the landing page will handle it after detecting trp_lang_switch=1
                    trpCookie.setCookie(trp_language_cookie_data['cookie_name'], clicked_language, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'], true);

                    // Add query param to signal deliberate language switch (for cross-domain)
                    if ( trp_language_cookie_data['domain_language_map'] ) {
                        e.preventDefault();
                        var separator = clicked_url.indexOf('?') !== -1 ? '&' : '?';
                        window.location.href = clicked_url + separator + 'trp_lang_switch=1';
                        return false;
                    }
                }
            }
        });
    };

    this.check_if_iphone_user = function (){
        
        if( trp_language_cookie_data['is_iphone_user_check'] == false ){
            return false;
        }else{
            if( /iPhone/g.test(navigator.userAgent) ){
                return true;
            }else{
                return false;
            }
        }
    };

    this.redirect_if_needed = function( needed_language ){
        // Skip cross-domain sync here — if redirect happens the landing page handles it, if not the cookie is already correct
        trpCookie.setCookie( trp_language_cookie_data['cookie_name'], needed_language, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'], true );
        _this.add_event_handlers();

        if (!(_this.is_same_language_code(_this.get_current_dom_language(), needed_language)) && _this.check_if_iphone_user() == false ){
            url_to_redirect = _this.get_url_for_lang( needed_language );
            if(url_to_redirect != 'undefined' && url_to_redirect!= false ) {
                // redirect to needed language
                if(trp_language_cookie_data['popup_type'] == 'normal_popup' && trp_language_cookie_data['popup_option'] == 'popup'){
                    _this.activate_popup( needed_language, url_to_redirect );
                }else{
                    if(trp_language_cookie_data['popup_type'] == 'hello_bar' && trp_language_cookie_data['popup_option'] == 'popup'){
                        _this.activate_hello_bar(needed_language, url_to_redirect);
                    }else {
                        window.location.replace( url_to_redirect );
                    }
                }
            }
        }
    };

    this.initialize = function (){
        trpCookie = new TRP_IN_Cookie();
        trpHelper = new TRP_IN_Helper();
        if ( ! trpCookie.areCookiesEnabled() ){
            _this.add_event_handlers();
            return;
        }

        // Check if this is a deliberate language switch (query param from add_event_handlers)
        var urlParams = new URLSearchParams( window.location.search );
        if ( urlParams.has( 'trp_lang_switch' ) ) {
            // Remove the query param from URL first
            urlParams.delete( 'trp_lang_switch' );
            var newUrl = window.location.pathname + ( urlParams.toString() ? '?' + urlParams.toString() : '' ) + window.location.hash;
            history.replaceState( null, '', newUrl );

            // Deliberate switch - set cookie to current page language, no popup
            var currentLanguage = _this.get_lang_from_url( window.location.href );
            if ( currentLanguage ) {
                trpCookie.setCookie( trp_language_cookie_data['cookie_name'], currentLanguage, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );
                _this.add_event_handlers();
                return;
            }
            // If no domain language found (Multiple Domains not active), continue with normal detection
        }

        var language_from_cookie = trpCookie.getCookie( trp_language_cookie_data['cookie_name'] );
        if ( language_from_cookie && trpHelper.in_array( language_from_cookie, trp_language_cookie_data['publish_languages'] ) ) {
            // if cookie is set, redirect if needed
            _this.redirect_if_needed( language_from_cookie );
        }else{
            // if cookie is not set, send request to find out language and then redirect if needed
            _this.ajax_get_needed_language();
        }
    };

    _this.initialize();
}

/**
 * String manipulation functions
 */
function TRP_IN_Helper(){

    this.trailingslashit = function ( string ){
        string = string.replace(/\/+$/,'');
        string = string + '/';
        return string;
    };

    this.ltrim = function ( string ) {
        var trimmed = string.replace(/^\s+/g, '');
        return trimmed;
    };

    this.in_array = function (needle, haystack) {
        for(var i in haystack ) {
            if(haystack[i] == needle) {
                return true;
            }
        }
        return false;
    };

    this.array_search = function(val, array) {
        if(typeof(array) === 'array' || typeof(array) === 'object') {
            var rekey;
            for(var i in array) {
                if(array[i] == val) {
                    rekey = i;
                    break;
                }
            }
            return rekey;
        }
    };

    /**
     * Update url with query string.
     *
     */
    this.update_query_string = function(key, value, url) {
        if (!url) url = window.location.href;
        var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
            hash;

        if (re.test(url)) {
            if (typeof value !== 'undefined' && value !== null)
                return url.replace(re, '$1' + key + "=" + value + '$2$3');
            else {
                hash = url.split('#');
                url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
                if (typeof hash[1] !== 'undefined' && hash[1] !== null)
                    url += '#' + hash[1];
                return url;
            }
        }
        else {
            if (typeof value !== 'undefined' && value !== null ) {
                var separator = url.indexOf('?') !== -1 ? '&' : '?';
                hash = url.split('#');
                url = hash[0] + separator + key + '=' + value;
                if (typeof hash[1] !== 'undefined' && hash[1] !== null)
                    url += '#' + hash[1];
                return url;
            }
            else
                return url;
        }
    };
}

/**
 * Manipulate cookie: set/get/erase
 * Includes cross-domain sync for Multiple Domains addon
 */
function TRP_IN_Cookie() {
    var _this = this;

    // Track if sync is in progress to prevent duplicate syncs
    this.syncInProgress = false;

    /**
     * Set a cookie and trigger cross-domain sync if enabled
     *
     * @param {boolean} skipSync - Skip cross-domain sync (e.g. when navigating away immediately)
     */
    this.setCookie = function(cname, cvalue, exdays, cpath, skipSync) {
        var d = new Date();
        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
        var expires = "expires=" + d.toUTCString();
        document.cookie = cname + "=" + cvalue + ";" + expires + ";path=" + cpath + ";SameSite=Lax";

        // Trigger cross-domain sync if this is the language cookie
        if ( cname === trp_language_cookie_data['cookie_name'] && !skipSync ) {
            _this.syncToOtherDomains( cvalue );
        }
    };

    this.getCookie = function(cname) {
        var name = cname + "=";
        var ca = document.cookie.split(';');
        for(var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    };

    this.eraseCookie = function(name) {
        document.cookie = name+'=; Max-Age=-99999999;';
    };

    this.areCookiesEnabled = function(){
        if (navigator.cookieEnabled) return true;

        // set and read cookie
        document.cookie = "cookietest=1";
        var ret = document.cookie.indexOf("cookietest=") != -1;

        // delete cookie
        document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";

        return ret;
    };

    /**
     * Sync cookie to all other configured domains (Multiple Domains support)
     *
     * @param {string} cookieValue - The language code to sync
     */
    this.syncToOtherDomains = function( cookieValue ) {
        // Check if sync is enabled and ajax URLs exist
        if ( !trp_language_cookie_data['sync_enabled'] ||
             !trp_language_cookie_data['sync_ajax_urls'] ||
             _this.syncInProgress ) {
            return;
        }

        _this.syncInProgress = true;

        var currentDomain = trp_language_cookie_data['current_domain'];
        var ajaxUrls = trp_language_cookie_data['sync_ajax_urls'];

        for ( var language in ajaxUrls ) {
            if ( !ajaxUrls.hasOwnProperty( language ) ) {
                continue;
            }

            var ajaxUrl = ajaxUrls[ language ];

            // Skip if this ajax URL is on the current domain
            if ( ajaxUrl.indexOf( currentDomain ) === 0 ) {
                continue;
            }

            _this.injectSyncIframe( ajaxUrl, cookieValue );
        }

        // Reset sync flag after a delay
        setTimeout( function() {
            _this.syncInProgress = false;
        }, 5000 );
    };

    /**
     * Inject hidden iframe to set cookie on another domain via REST API
     *
     * @param {string} restUrl - Target REST API URL
     * @param {string} cookieValue - Cookie value to set
     */
    this.injectSyncIframe = function( restUrl, cookieValue ) {
        var iframe = document.createElement( 'iframe' );
        iframe.style.display = 'none';
        iframe.className = 'trp-ald-sync-iframe';
        iframe.src = restUrl + '?trp_ald_cv=' + encodeURIComponent( cookieValue );

        // Remove iframe after load or timeout
        iframe.onload = function() {
            setTimeout( function() {
                if ( iframe.parentNode ) {
                    iframe.parentNode.removeChild( iframe );
                }
            }, 1000 );
        };

        // Fallback: remove after timeout even if onload doesn't fire
        setTimeout( function() {
            if ( iframe.parentNode ) {
                iframe.parentNode.removeChild( iframe );
            }
        }, 10000 );

        document.body.appendChild( iframe );
    };
}


jQuery( function() {
    trpDetermineLanguage = new TRP_IN_Determine_Language();
});
// source --> https://www.s-techworks.at/wp-content/plugins/translatepress-multilingual/assets/js/trp-frontend-language-switcher.js?ver=3.1.5 
class BaseSwitcher {
    constructor(rootEl) {
        this.root = rootEl;
        this.list = rootEl?.querySelector('.trp-switcher-dropdown-list') || null;
        this.isOpen = false;
        this._pendingFocusOnOpen = false;
        if (!this.root || !this.list) return;

        if (!this.list.id) {
            this.list.id = `trp-list-${Math.random().toString(36).slice(2, 9)}`;
        }

        // Single transitionend handler to drop .is-transitioning and finalize hidden/inert
        this._onTe = (e) => {
            if (e.target !== this.list || e.propertyName !== 'max-height') return;

            this.root.classList.remove('is-transitioning');

            if (!this.isOpen) {
                this.list.hidden = true;
                this.list.setAttribute('inert', '');
            } else if (this._pendingFocusOnOpen) {
                this._pendingFocusOnOpen = false;
                const first = this.list.querySelector(
                    '[role="option"], a, button, [tabindex]:not([tabindex="-1"])'
                );
                first?.focus?.({ preventScroll: true });
            }
        };
        this.list.addEventListener('transitionend', this._onTe);

        this.collapse();
        this.setAutoWidth();
        this.bindKeyboard();
    }

    /**
     * Returns true if the list has a non-zero transition duration (for any property).
     * We use this to decide whether to rely on `transitionend` or fall back to sync behavior.
     */
    _hasAnimatedTransition() {
        if (!this.list) return false;

        const cs = getComputedStyle(this.list);
        const durationsRaw = cs.transitionDuration || '';

        if (!durationsRaw) return false;

        const durations = durationsRaw
            .split(',')
            .map(str => parseFloat(str) || 0);

        return durations.some(d => d > 0);
    }

    collapse() {
        this.list.hidden = true;
        this.list.setAttribute('inert', '');
        this.setExpanded(false);
        this.root.classList.remove('is-transitioning');
    }

    /**
     * If width is set to auto, fix it to the calculated width + 20px
     * We do this in order to avoid width shift on hover
     * */
    setAutoWidth() {
        const bonusWidth = 10;

        const cs = getComputedStyle(this.root);
        const declaredWidth = cs.getPropertyValue('--switcher-width').trim();

        if (declaredWidth === 'auto' && this.root.querySelector('.trp-language-item-name')) { // In case trp-language-item-name is not present, we are in flags only mode - so no auto width sizing is needed
            const initialWidth = this.root.getBoundingClientRect().width;

            this.root.style.setProperty('--switcher-width', (initialWidth + bonusWidth) + 'px');
        }
    }

    setExpanded(open) {
        const trigger = this.root.querySelector('.trp-language-item__current[role="button"]');
        const val = String( !!open );
        trigger?.setAttribute('aria-expanded', val);
        this.root.classList.toggle('is-open', !!open);
    }

    setOpen( open, { source = null } = {} ) {
        if ( !this.root || !this.list || open === this.isOpen ) return;

        const prefersReduced = window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches;
        const hasTransition  = !prefersReduced && this._hasAnimatedTransition();

        this.isOpen = open;

        // No transitions (0s duration) OR reduced motion: do everything synchronously,
        if ( !hasTransition ) {
            if ( open ) {
                this.list.hidden = false;
                this.list.removeAttribute( 'inert' );
                this.setExpanded( true );

                this._pendingFocusOnOpen = ( source?.type === 'keydown' );
                if ( this._pendingFocusOnOpen ) {
                    this._pendingFocusOnOpen = false;
                    const first = this.list.querySelector(
                        '[role="option"], a, button, [tabindex]:not([tabindex="-1"])'
                    );
                    first?.focus?.({ preventScroll: true });
                }
            } else {
                this.setExpanded( false );
                this.list.hidden = true;
                this.list.setAttribute( 'inert', '' );
                this._pendingFocusOnOpen = false;
            }
            return;
        }

        // Animated path: rely on transitionend to remove .is-transitioning
        if ( open ) {
            // Must be visible for CSS transition to run
            this.list.hidden = false;
            this.list.removeAttribute( 'inert' );

            this._pendingFocusOnOpen = ( source?.type === 'keydown' );

            this.root.classList.add( 'is-transitioning' );
            // Next frame so browser registers pre-open (max-height: 0) state
            requestAnimationFrame( () => this.setExpanded( true ) );
        } else {
            this.root.classList.add( 'is-transitioning' );
            this.setExpanded( false );
        }
    }

    bindKeyboard() {
        const trigger = this.root.querySelector('.trp-language-item__current[role="button"]');
        if ( !trigger ) return;

        trigger.addEventListener('keydown', (e) => {
            const inList = !!e.target.closest?.('.trp-switcher-dropdown-list');

            if ( e.key === 'Enter' || e.key === ' ' ) {
                e.preventDefault();
                this.setOpen(!this.isOpen, { source: e });
                return;
            }

            if ( e.key === 'ArrowDown' && !this.isOpen ) {
                e.preventDefault();
                this.setOpen(true, { source: e });
            }

            if ( e.key === 'Escape' ) {
                this.setOpen(false, { source: e });
                trigger.focus?.();
            }
        });
    }
}

class ShortcodeSwitcher extends BaseSwitcher {
    constructor(wrapper) {
        const overlay =
                  wrapper.querySelector('.trp-language-switcher.trp-shortcode-overlay')
                  || [...wrapper.querySelectorAll('.trp-language-switcher')]
                      .find(el => el.classList.contains('trp-shortcode-overlay'));

        // Overlay must be interactable; ensure no accidental hidden/inert from server
        overlay.hidden = false;
        overlay.removeAttribute('hidden');
        overlay.removeAttribute('inert');
        if ('inert' in overlay) overlay.inert = false;

        super(overlay);

        if (!this.root || !this.list) return;

        const control = this.root.querySelector('.trp-language-item__current[role="button"]');
        if (control && this.list && !control.hasAttribute('aria-controls')) {
            control.setAttribute('aria-controls', this.list.id);
        }

        const isClickMode =
                  this.root.classList.contains('trp-open-on-click') ||
                  wrapper.dataset.openMode === 'click' ||
                  wrapper.classList.contains('trp-open-on-click');

        if (isClickMode) {
            // Click anywhere on overlay EXCEPT inside the list
            this.root.addEventListener('click', (e) => {
                const inList = e.target.closest('.trp-switcher-dropdown-list');
                if (!inList) {
                    e.preventDefault();
                    e.stopPropagation();
                    this.setOpen(!this.isOpen, { source: e });
                }
            }, true);

            // Outside click closes
            this.onDocClick = (evt) => {
                if (!wrapper.contains(evt.target)) this.setOpen(false, { source: evt });
            };
            document.addEventListener('click', this.onDocClick, true);

            // Focus leaving wrapper closes
            wrapper.addEventListener('focusout', () => {
                setTimeout(() => {
                    if (!wrapper.contains(document.activeElement)) {
                        this.setOpen(false, { source: 'keyboard' });
                    }
                }, 0);
            });
        } else {
            // Hover mode on overlay
            this.root.addEventListener('mouseenter', (e) => this.setOpen(true,  { source: e }));
            this.root.addEventListener('mouseleave', (e) => this.setOpen(false, { source: e }));
        }
    }
}

class FloaterSwitcher extends BaseSwitcher {
    constructor(el) {
        super(el);

        el.addEventListener('mouseenter', (e) => this.setOpen(true,  { source: e }));
        el.addEventListener('mouseleave', (e) => this.setOpen(false, { source: e }));

        this.onDocClick = (evt) => { if (!el.contains(evt.target)) this.setOpen(false, { source: evt }); };
        document.addEventListener('click', this.onDocClick, true);
    }
}

document.addEventListener('DOMContentLoaded', () => {
    // Front-end or classic admin
    initLanguageSwitchers(document);

    // If no wrapper and we are in Gutenberg, watch for async SSR insert
    if (
        inGutenberg() &&
        !getEditorDoc().querySelector(WRAPPER)
    ) {
        observeWrapperUntilFound();
    }

    if ( !inGutenberg() )
        observeShortcodeSwitcher();
});

/** For shortcode switcher
 *  Mark the shortcodes that were initialized
 * */
const TRP_BOUND = new WeakSet();
const mark = (el) => TRP_BOUND.add(el);
const isMarked = (el) => TRP_BOUND.has(el);

const WRAPPER = '.trp-shortcode-switcher__wrapper';
const OVERLAY = '.trp-language-switcher:not(.trp-opposite-button)';

// Helpers
function inGutenberg() {
    return document.body?.classList?.contains('block-editor-page')
        || !!(window.wp?.data?.select?.('core/block-editor'));
}

// If editor uses an iframe canvas, work inside it
function getEditorDoc() {
    const ifr = document.querySelector('iframe[name="editor-canvas"], .editor-canvas__iframe');

    return (ifr && ifr.contentDocument) ? ifr.contentDocument : document;
}

function initLanguageSwitchers(root = document) {
    const floater = root.querySelector(
        '.trp-language-switcher.trp-ls-dropdown:not(.trp-shortcode-switcher):not(.trp-opposite-language)'
    );

    if (floater)
        new FloaterSwitcher(floater);

    root.querySelectorAll(WRAPPER)
        .forEach(wrapper => {
            const overlay = wrapper.querySelector('.trp-language-switcher:not(.trp-opposite-button)');

            if (overlay && !isMarked(overlay)) {
                mark(overlay);
                new ShortcodeSwitcher(wrapper);
            }
        });
}

/**
 * Observes the document for dynamically inserted shortcode switchers and initializes them automatically when detected.
 */
function observeShortcodeSwitcher() {
    const initWrapper = ( wrapper ) => {
        if ( !wrapper )
            return;

        const overlay = wrapper.querySelector( OVERLAY );

        if ( !overlay || isMarked( overlay ) )
            return;

        mark( overlay );

        new ShortcodeSwitcher( wrapper );
    }

    const mo = new MutationObserver( ( mutations ) => {
        for ( const m of mutations ) {
            for ( const n of m.addedNodes ) {
                if ( n.nodeType !== 1 )
                    continue;

                if ( n.matches?.( WRAPPER ) )
                    initWrapper( n );

                n.querySelectorAll?.( WRAPPER ).forEach( initWrapper );
            }
        }
    });

    mo.observe( document, { childList: true, subtree: true } );
}

/**
 * Observe Gutenberg for the shortcode wrapper being inserted asynchronously.
 *
 * Supports both Blocks API v2 (no editor iframe; wrapper appears in the outer document)
 * and Blocks API v3 (editor content rendered inside an iframe canvas).
 *
 * Strategy:
 *  1) Check the current editor document for `.trp-shortcode-switcher__wrapper` and init immediately.
 *  2) If an editor canvas iframe exists, watch its document (and reattach on iframe load) for the wrapper.
 *  3) If no iframe yet, watch the outer document for either the iframe (v3) or the wrapper itself (v2).
 *
 * Initialization is performed once per context to avoid duplicate bindings.
 */
function observeWrapperUntilFound() {
    // If wrapper already exists in current editor doc, init
    const edDoc = getEditorDoc();
    const existing = edDoc.querySelector(WRAPPER);

    if ( existing ) {
        initLanguageSwitchers( edDoc );
        return;
    }

    // Helper to locate the editor canvas iframe in the OUTER document
    const findCanvasIframe = () => document.querySelector('iframe[name="editor-canvas"], .editor-canvas__iframe');

    // If iframe is already present in the outer doc, start watching inside it
    const iframeNow = findCanvasIframe();
    if ( iframeNow ) {
        watchIframe( iframeNow );
        return;
    }

    // Otherwise, observe the OUTER document until the iframe appears
    const outerMO = new MutationObserver( ( mutations ) => {
        for ( const m of mutations ) {
            for ( const n of m.addedNodes ) {
                if ( n.nodeType !== 1 ) continue;

                const iframe =
                          n.matches?.('iframe[name="editor-canvas"], .editor-canvas__iframe')
                              ? n
                              : n.querySelector?.('iframe[name="editor-canvas"], .editor-canvas__iframe');

                if ( iframe ) {
                    outerMO.disconnect();
                    watchIframe( iframe );
                    return;
                }

                // Also catch shortcode wrapper added directly to the outer document (API v2, no iframe)
                const wrapper =
                          n.matches?.(WRAPPER)
                              ? n
                              : n.querySelector?.(WRAPPER);

                if ( wrapper ) {
                    outerMO.disconnect();
                    initLanguageSwitchers( document );
                    return;
                }

            }
        }
    } );
    outerMO.observe( document, { childList: true, subtree: true } );

    function watchIframe( iframe ) {
        // Try immediately (some builds inject srcdoc synchronously)
        tryAttachInside();

        // Also on load/navigate (Gutenberg may reload the canvas)
        iframe.addEventListener( 'load', tryAttachInside );

        function tryAttachInside() {
            let doc;
            try {
                doc = iframe.contentDocument || iframe.contentWindow?.document;
            } catch (e) {
                console.warn('Cannot access iframe content due to cross-origin restrictions', e);
                return;
            }
            if ( !doc ) return;

            // If wrapper is already there, init once and stop.
            const hit = doc.querySelector(WRAPPER);
            if ( hit ) {
                initLanguageSwitchers( doc );
                return;
            }

            // Observe INSIDE the iframe until wrapper appears
            const innerMO = new MutationObserver( ( muts ) => {
                for ( const mm of muts ) {
                    for ( const nn of mm.addedNodes ) {
                        if ( nn.nodeType !== 1 ) continue;
                        if (
                            nn.matches?.(WRAPPER) ||
                            nn.querySelector?.(WRAPPER)
                        ) {
                            innerMO.disconnect();
                            initLanguageSwitchers( doc );
                            return;
                        }
                    }
                }
                if ( doc.querySelector(WRAPPER) ) {
                    innerMO.disconnect();
                    initLanguageSwitchers( doc );
                }
            } );

            innerMO.observe( doc, { childList: true, subtree: true } );
        }
    }
};