
function xImageHotspots(){

    const extrasImageHotspots = function ( container ) {

        bricksQuerySelectorAll(container, '.brxe-ximagehotspots').forEach( imageHotspot => {
 
            const configAttr = imageHotspot.getAttribute('data-x-hotspots')
            const config = configAttr ? JSON.parse(configAttr) : {}
            
            // Check if we're in the Bricks builder
            const isBuilder = document.querySelector('body > .brx-body.iframe');
            
            // In builder, close all popovers when clicking on the hotspots background
            // Only for nested elements (those with .x-marker_popover-wrapper)
            const hasNestedElements = imageHotspot.querySelector('.x-marker_popover-wrapper');
            if (isBuilder && hasNestedElements && !imageHotspot._hasClickHandler) {
                imageHotspot.addEventListener('click', (e) => {
                    // Only close if clicking directly on the hotspots element, not on markers
                    if (e.target === imageHotspot || e.target.closest('.x-image-hotspots_inner') === e.target) {
                        imageHotspot.querySelectorAll('.x-marker_popover-wrapper[data-show]').forEach(wrapper => {
                            wrapper.removeAttribute('data-show');
                            const marker = wrapper.closest('.x-marker');
                            const trigger = marker?.querySelector('.x-marker_marker-trigger');
                            if (trigger) {
                                trigger.setAttribute('aria-expanded', 'false');
                            }
                        });
                    }
                });
                imageHotspot._hasClickHandler = true;
            }
            
            imageHotspot.querySelectorAll('.x-marker').forEach( (marker, index) => {

                if ( marker.querySelector('.x-marker_marker-trigger') ) {

                    const trigger = marker.querySelector('.x-marker_marker-trigger');
                    
                    // Get marker-specific config or fall back to parent config
                    const markerConfigAttr = marker.getAttribute('data-x-hotspots-marker');
                    const markerConfig = markerConfigAttr ? JSON.parse(markerConfigAttr) : {};
                    
                    // Whitelist for valid placement values
                    const validPlacements = [
                        'top', 'right', 'bottom', 'left', 'auto',
                        'auto-start', 'auto-end',
                        'top-start', 'top-end',
                        'right-start', 'right-end',
                        'bottom-start', 'bottom-end',
                        'left-start', 'left-end'
                    ];
                    
                    // Whitelist for valid interaction values
                    const validInteractions = [
                        'click',
                        'mouseenter focus',
                        'mouseenter click'
                    ];
                    
                    // Validate placement value
                    const markerPlacement = markerConfig.placement && validPlacements.includes(markerConfig.placement) 
                        ? markerConfig.placement 
                        : config.placement;
                    
                    // Validate interaction value
                    const markerInteraction = markerConfig.interaction && validInteractions.includes(markerConfig.interaction)
                        ? markerConfig.interaction
                        : config.interaction;
                    
                    // Merge configs: marker-specific overrides parent config
                    const effectiveConfig = {
                        placement: markerPlacement,
                        offsetSkidding: markerConfig.offsetSkidding !== undefined ? markerConfig.offsetSkidding : config.offsetSkidding,
                        offsetDistance: markerConfig.offsetDistance !== undefined ? markerConfig.offsetDistance : config.offsetDistance,
                        moveTransition: markerConfig.moveTransition !== undefined ? markerConfig.moveTransition : config.moveTransition,
                        interaction: markerInteraction,
                        moveFocus: markerConfig.moveFocus !== undefined ? markerConfig.moveFocus : config.moveFocus,
                    };
                    
                    // In builder, don't destroy/recreate - just update if exists
                    if (isBuilder && trigger._tippy) {
                        // Instance already exists, just update positioning options
                        trigger._tippy.setProps({
                            placement: effectiveConfig.placement,
                            offset: [ effectiveConfig.offsetSkidding , effectiveConfig.offsetDistance],
                        });
                        return; // Skip recreation
                    }
                    
                    // Destroy existing instance in frontend only
                    if (!isBuilder && trigger._tippy) {
                        trigger._tippy.destroy();
                    }

                    let markerTrigger = trigger.tagName == 'BUTTON' ? effectiveConfig.interaction : 'mouseenter focus';
                    let markerInteractive = trigger.tagName == 'BUTTON' ? true : false;

                    // In builder, use Popper.js directly for positioning only (only for nested elements with wrapper)
                        const popoverWrapper = marker.querySelector('.x-marker_popover-wrapper');
                     
                    if (isBuilder && popoverWrapper) {
                        // This is a nested element setup - use Popper.js for positioning only
                        
                        // If Popper instance already exists, just update options and skip re-initialization
                        if (trigger._popperInstance) {
                            trigger._popperInstance.setOptions({
                                placement: effectiveConfig.placement || 'bottom',
                                modifiers: [
                                    {
                                        name: 'offset',
                                        options: {
                                            offset: [effectiveConfig.offsetSkidding || 0, effectiveConfig.offsetDistance || 10],
                                        },
                                    },
                                ],
                            });
                            return; // Skip re-initialization
                        }
                        
                        // Create Popper instance for positioning only
                        const popperInstance = Popper.createPopper(trigger, popoverWrapper, {
                            placement: effectiveConfig.placement || 'bottom',
                            modifiers: [
                                {
                                    name: 'offset',
                                    options: {
                                        offset: [effectiveConfig.offsetSkidding || 0, effectiveConfig.offsetDistance || 10],
                                    },
                                },
                                {
                                    name: 'preventOverflow', 
                                    options: {
                                        boundary: 'viewport',
                                    },
                                },
                            ],
                        });
                        
                        // Manual show/hide for builder
                        const showPopover = () => {
                            popoverWrapper.setAttribute('data-show', '');
                            trigger.setAttribute('aria-expanded', 'true');
                            popperInstance.update();
                        };
                        
                        const hidePopover = () => {
                            popoverWrapper.removeAttribute('data-show');
                            trigger.setAttribute('aria-expanded', 'false');
                        };
                        
                        // Add click handler for button (only once)
                        if (trigger.tagName === 'BUTTON') {
                            trigger.addEventListener('click', (e) => {
                                e.stopPropagation(); // Prevent immediate close from hotspots click
                                const isShown = popoverWrapper.hasAttribute('data-show');
                                
                                // Close all other popovers in this hotspots element
                                imageHotspot.querySelectorAll('.x-marker_popover-wrapper[data-show]').forEach(otherWrapper => {
                                    if (otherWrapper !== popoverWrapper) {
                                        otherWrapper.removeAttribute('data-show');
                                        const otherMarker = otherWrapper.closest('.x-marker');
                                        const otherTrigger = otherMarker?.querySelector('.x-marker_marker-trigger');
                                        if (otherTrigger) {
                                            otherTrigger.setAttribute('aria-expanded', 'false');
                                        }
                                    }
                                });
                                
                                // Toggle this popover
                                if (isShown) {
                                    hidePopover();
                                } else {
                                    showPopover();
                                }
                            });
                        }
                        
                        // Store instance
                        trigger._popperInstance = popperInstance;
                        
                        return; // Skip Tippy initialization in builder
                    }
                    
                    // Frontend: Use Tippy normally
                    let tippyOptions = {
                        allowHTML: true,     
                        interactive: markerInteractive, 
                        arrow: true,
                        trigger: markerTrigger,
                        placement: effectiveConfig.placement,
                        maxWidth: 'none',    
                        animation: 'extras',
                        theme: 'extras',     
                        touch: true, 
                        duration: 0, // Disable Tippy's inline transition-duration, use CSS variables instead
                        moveTransition: 'transform ' + effectiveConfig.moveTransition + 'ms ease-out', 
                        offset: [ effectiveConfig.offsetSkidding , effectiveConfig.offsetDistance],
                        content: marker.querySelector('.x-marker_popover-content'),
                        appendTo: marker.querySelector('.x-marker_popover'),
                    };
                    
                    if (trigger.tagName == 'A') {
                        tippyOptions.interactive = true;
                    } 

                    let instance = tippy(trigger, tippyOptions); 
                    instance.setProps({ 
                        onShow(instance) {
                            // Set aria-expanded for accessibility (especially needed in builder with render())
                            if (trigger.tagName === 'BUTTON') {
                                trigger.setAttribute('aria-expanded', 'true');
                            }
                            
                            marker.addEventListener('keydown', function(e) {
                                if((e.key === "Escape" || e.key === "Esc")){ 
                                    instance.hide();
                                }
                            })

                            if ( effectiveConfig.moveFocus && marker.querySelector('.tippy-content') ) {
                                if ( 
                                    !marker.querySelector('.tippy-content a[href]:first-child') &&
                                    !marker.querySelector('.tippy-content h1:first-child > a[href]')  && 
                                    !marker.querySelector('.tippy-content h2:first-child > a[href]')  && 
                                    !marker.querySelector('.tippy-content h3:first-child > a[href]')  && 
                                    !marker.querySelector('.tippy-content h4:first-child > a[href]')  && 
                                    !marker.querySelector('.tippy-content h5:first-child > a[href]')  &&
                                    !marker.querySelector('.tippy-content h6:first-child > a[href]')  && 
                                    !marker.querySelector('.tippy-content button:first-child') &&
                                    !marker.querySelector('.tippy-content input:first-child') &&
                                    !marker.querySelector('.tippy-content textarea:first-child') &&
                                    !marker.querySelector('.tippy-content select:first-child') &&
                                    !marker.querySelector('.tippy-content details:first-child') &&
                                    !marker.querySelector('.tippy-content [tabindex]:not([tabindex="-1"]:first-child') ) {
                                    marker.querySelector('.tippy-content').addEventListener('blur', function(e) {
                                        instance.hide();
                                    })
                                }
                            }
                        },
                        onShown(instance) {

                            // Initialize BricksExtras elements inside popover content
                            const popoverContent = marker.querySelector('.x-marker_popover-content');
                            if (popoverContent && typeof xBricksExtrasElementsInit === 'function') {
                                xBricksExtrasElementsInit(popoverContent);
                            }

                             /* ensure media player playable */
                            if ( marker.querySelector('media-controls') ) {
                                marker.querySelectorAll('media-controls').forEach(mediaControls => {
                                    mediaControls.style.removeProperty('display');
                                })
                            } 

                            marker.querySelectorAll('[data-x-close]').forEach(closeButton => {
                                closeButton.addEventListener('click', () => {
                                    instance.hide()
                                })
                            })

                                marker.dispatchEvent(new Event('x_popover:show'))
                                imageHotspot.dispatchEvent(new Event('x_image_hotspot:selected_' + index))
                                
                                if ( effectiveConfig.moveFocus && marker.querySelector('button.x-marker_marker') ) {

                                    marker.querySelector('button.x-marker_marker').addEventListener('keydown', function(e) {

                                        if ( e.code === 'Tab' && !e.shiftKey ){

                                                if ( marker.querySelector('.tippy-content .x-marker_popover-content') ) {

                                                    marker.querySelector('.tippy-content').setAttribute('tabindex', '0')
                                
                                                    if ( 
                                                        !marker.querySelector('.tippy-content a[href]:first-child') &&
                                                        !marker.querySelector('.tippy-content h1:first-child > a[href]')  && 
                                                        !marker.querySelector('.tippy-content h2:first-child > a[href]')  && 
                                                        !marker.querySelector('.tippy-content h3:first-child > a[href]')  && 
                                                        !marker.querySelector('.tippy-content h4:first-child > a[href]')  && 
                                                        !marker.querySelector('.tippy-content h5:first-child > a[href]')  &&
                                                        !marker.querySelector('.tippy-content h6:first-child > a[href]')  && 
                                                        !marker.querySelector('.tippy-content button:first-child') &&
                                                        !marker.querySelector('.tippy-content input:first-child') &&
                                                        !marker.querySelector('.tippy-content textarea:first-child') &&
                                                        !marker.querySelector('.tippy-content select:first-child') &&
                                                        !marker.querySelector('.tippy-content details:first-child') &&
                                                        !marker.querySelector('.tippy-content [tabindex]:not([tabindex="-1"]:first-child') ) {
                        
                                                            e.preventDefault() 
                                                            marker.querySelector('.tippy-content').focus()
                        
                                                        }
                        
                                                }
                                            
                                        }
                                    });
                                }

                        },
                        onHide(instance) {
                            // Reset aria-expanded when hiding
                            if (trigger.tagName === 'BUTTON') {
                                trigger.setAttribute('aria-expanded', 'false');
                            }
                        }
                    });


                    if ( marker.querySelector('a.x-marker_marker') ) {
                        marker.querySelector('a.x-marker_marker').addEventListener('click', () => {
                            imageHotspot.dispatchEvent(new Event('x_image_hotspot:selected_' + index))
                        })
                    }

                    if (window.xHotspots){
                        window.xHotspots.Instances[marker.dataset.xId] = instance;
                    }

                    if ( marker.querySelector('.x-marker_marker') ) {
                        marker.querySelector('.x-marker_marker').addEventListener('focus', () => {
                            tippy.hideAll({exclude: instance})
                        })
                    }

                }

            })

        })

    }


    extrasImageHotspots(document) 

    const xImageHotspotsAJAX = xExtrasRegisterAJAXHandler('doExtrasImageHotspots', true, '.brxe-ximagehotspots');
 
    // Expose function
    window.doExtrasImageHotspots = extrasImageHotspots;

}

document.addEventListener("DOMContentLoaded",function(e){
    
    if ( !bricksIsFrontend ) {
        return;
    }

    xImageHotspots()
})
