(function() {
    // Get template data and configuration
    const templateData = document.getElementById('template-data');
    const type = templateData.getAttribute('data-type');
    const hardCacheEnabled = templateData.getAttribute('data-hard-cache-enabled') === 'true';
    
    // Track all favicon/image elements and their IDs
    let allMediaElements = [];
    let allMediaIds = [];
    const mediaMap = new Map();

    // Add loading effects to image/favicon and associated text
    function addLoadingEffects(imgElement) {
        const container = imgElement.closest(type === 'image' ? '.image' : '.result_item');
        if (!container) return;

        const titleSelector = type === 'image' ? '.img_title' : '.result-url';
        const title = container.querySelector(titleSelector);
        imgElement.closest('.favicon-wrapper')?.classList.add('loading');
        // if (title) title.classList.add('title-loading');
    }

    // Remove loading effects when image/favicon loads
    function removeLoadingEffects(imgElement) {
        const container = imgElement.closest(type === 'image' ? '.image' : '.result_item');
        const titleSelector = type === 'image' ? '.img_title' : '.result-url';
        const title = container?.querySelector(titleSelector);
        imgElement.closest('.favicon-wrapper')?.classList.remove('loading');
        if (title) title.classList.remove('title-loading');
        
        if (type === 'image' && imgElement.src.endsWith('/images/globe.svg')) {
            container.remove();
        }
    }

    // Handle image/favicon loading errors
    function handleImageError(imgElement, retryCount = 8, retryDelay = 500) {
        const isFavicon = !!imgElement.closest('.favicon-wrapper');
        const container = imgElement.closest(type === 'image' ? '.image' : '.result_item');
        const titleSelector = type === 'image' ? '.img_title' : '.result-url';
        const title = container?.querySelector(titleSelector);
        const fullURL = imgElement.getAttribute('data-full');

        if (retryCount > 0 && !imgElement.dataset.checked404) {
            imgElement.dataset.checked404 = '1'; // avoid infinite loop

            fetch(fullURL, { method: 'HEAD' })
                .then(res => {
                    if (res.status === 404) {
                        fallbackToGlobe(imgElement);
                    } else {
                        setTimeout(() => {
                            imgElement.src = fullURL;
                            imgElement.onerror = () => handleImageError(imgElement, retryCount - 1, retryDelay);
                        }, retryDelay);
                    }
                })
                .catch(() => {
                    fallbackToGlobe(imgElement);
                });
        } else {
            fallbackToGlobe(imgElement);
        }

        function fallbackToGlobe(imgElement) {
            imgElement.closest('.favicon-wrapper')?.classList.remove('loading');
            if (title) title.classList.remove('title-loading');

            if (isFavicon) {
                const wrapper = imgElement.closest('.favicon-wrapper') || imgElement.parentElement;
                const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
                svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
                svg.setAttribute("viewBox", "0 -960 960 960");
                svg.setAttribute("height", imgElement.height || "16");
                svg.setAttribute("width", imgElement.width || "16");
                svg.setAttribute("fill", "currentColor");
                svg.classList.add("favicon", "globe-fallback");
                svg.innerHTML = `<path d="M480-80q-82 0-155-31.5t-127.5-86Q143-252 111.5-325T80-480q0-83 31.5-155.5t86-127Q252-817 325-848.5T480-880q83 0 155.5 31.5t127 86q54.5 54.5 86 127T880-480q0 82-31.5 155t-86 127.5q-54.5 54.5-127 86T480-80Zm0-82q26-36 45-75t31-83H404q12 44 31 83t45 75Zm-104-16q-18-33-31.5-68.5T322-320H204q29 50 72.5 87t99.5 55Zm208 0q56-18 99.5-55t72.5-87H638q-9 38-22.5 73.5T584-178ZM170-400h136q-3-20-4.5-39.5T300-480q0-21 1.5-40.5T306-560H170q-5 20-7.5 39.5T160-480q0 21 2.5 40.5T170-400Zm216 0h188q3-20 4.5-39.5T580-480q0-21-1.5-40.5T574-560H386q-3 20-4.5 39.5T380-480q0 21 1.5 40.5T386-400Zm268 0h136q5-20 7.5-39.5T800-480q0-21-2.5-40.5T790-560H654q3 20 4.5 39.5T660-480q0 21-1.5 40.5T654-400Zm-16-240h118q-29-50-72.5-87T584-782q18 33 31.5 68.5T638-640Zm-234 0h152q-12-44-31-83t-45-75q-26 36-45 75t-31 83Zm-200 0h118q9-38 22.5-73.5T376-782q-56 18-99.5 55T204-640Z"/>`;
                imgElement.remove();
                wrapper.appendChild(svg);
            } else if (type === 'image') {
                container?.remove();
            }
        }
    }

    // Shared configuration
    const statusCheckInterval = 500;
    const scrollThreshold = 500;
    const loadingIndicator = document.getElementById('message-bottom-right');
    let loadingTimer;
    let isFetching = false;
    let page = parseInt(templateData.getAttribute('data-page')) || 1;
    let query = templateData.getAttribute('data-query');
    let noMoreImages = false;

    function showLoadingMessage() {
        loadingIndicator.classList.add('visible');
    }
    
    function hideLoadingMessage() {
        loadingIndicator.classList.remove('visible');
    }

    function ensureScrollable() {
        if (noMoreImages) return;
        if (document.body.scrollHeight <= window.innerHeight) {
            fetchNextPage();
        }
    }

    // Register a new media element for tracking
    function registerMediaElement(imgElement) {
        const id = imgElement.getAttribute('data-id');
        if (!id) return;
    
        let wrapper = imgElement.closest('.favicon-wrapper');
        if (!wrapper) {
            wrapper = document.createElement('span');
            wrapper.classList.add('favicon-wrapper');
            imgElement.replaceWith(wrapper);
            wrapper.appendChild(imgElement);
        }
    
        addLoadingEffects(imgElement);
    
        if (hardCacheEnabled) {
            imgElement.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
            imgElement.onerror = () => handleImageError(imgElement, 3, 1000);
        } else {
            imgElement.src = imgElement.getAttribute('data-full');
            imgElement.onload = () => removeLoadingEffects(imgElement);
            imgElement.onerror = () => handleImageError(imgElement, 3, 1000);
        }
    
        // Track it
        if (!mediaMap.has(id)) {
            mediaMap.set(id, []);
        }
        mediaMap.get(id).push(imgElement);
    }    

    // Check status of all tracked media elements
    function checkMediaStatus() {
        const allIds = Array.from(mediaMap.keys());
        if (allIds.length === 0) return;
    
        const idGroups = [];
        for (let i = 0; i < allIds.length; i += 50) {
            idGroups.push(allIds.slice(i, i + 50));
        }
    
        const processGroups = async () => {
            const stillPending = new Map();
    
            for (const group of idGroups) {
                try {
                    const response = await fetch(`/image_status?image_ids=${group.join(',')}`);
                    const statusMap = await response.json();
    
                    group.forEach(id => {
                        const elements = mediaMap.get(id);
                        const resolved = statusMap[id];
                        if (!elements) return;
                        if (resolved && resolved !== 'pending') {
                            elements.forEach(img => {
                                img.src = resolved;
                                img.onload = () => removeLoadingEffects(img);
                                img.onerror = () => handleImageError(img);
                            });
                        } else {
                            stillPending.set(id, elements);
                        }
                    });
                } catch (err) {
                    console.error('Status check failed:', err);
                    group.forEach(id => {
                        if (mediaMap.has(id)) {
                            stillPending.set(id, mediaMap.get(id));
                        }
                    });
                }
            }
    
            mediaMap.clear();
            for (const [id, imgs] of stillPending) {
                mediaMap.set(id, imgs);
            }
        };
    
        processGroups();
    }    

    function fetchNextPage() {
        if (isFetching || noMoreImages) return;
        
        loadingTimer = setTimeout(() => {
            showLoadingMessage();
        }, 150);
        
        isFetching = true;
        page += 1;

        fetch(`/search?q=${encodeURIComponent(query)}&t=${type}&p=${page}&ajax=true`)
            .then(response => response.text())
            .then(html => {
                clearTimeout(loadingTimer);
                hideLoadingMessage();

                let tempDiv = document.createElement('div');
                tempDiv.innerHTML = html;
                let newItems = tempDiv.querySelectorAll(type === 'image' ? '.image' : '.result_item');

                if (newItems.length > 0) {
                    let resultsContainer = document.querySelector(type === 'image' ? '.images' : '.results');
                    newItems.forEach(item => {
                        let clonedItem = item.cloneNode(true);
                        resultsContainer.appendChild(clonedItem);

                        // Register any new media elements
                        const img = clonedItem.querySelector('img[data-id]');
                        if (img) {
                            registerMediaElement(img);
                        }
                    });

                    ensureScrollable();
                } else {
                    noMoreImages = true;
                }
                isFetching = false;
            })
            .catch(error => {
                clearTimeout(loadingTimer);
                hideLoadingMessage();
                console.error('Fetch error:', error);
                isFetching = false;
            });
    }

    // Initialize all existing media elements
    function initializeMediaElements() {
        document.querySelectorAll('img[data-id]').forEach(img => {
            registerMediaElement(img);
        });
    }

    function startStatusPolling() {
        checkMediaStatus();
        setInterval(checkMediaStatus, statusCheckInterval);
    }
    
    if (document.readyState === 'complete') {
        initializeMediaElements();
        if (hardCacheEnabled) startStatusPolling();
    } else {
        window.addEventListener('load', () => {
            initializeMediaElements();
            if (hardCacheEnabled) startStatusPolling();
        });
    }    

    // Infinite scroll handler
    window.addEventListener('scroll', () => {
        if (isFetching || noMoreImages) return;
        if (window.innerHeight + window.scrollY >= document.body.offsetHeight - scrollThreshold) {
            fetchNextPage();
        }
    });

    // // Clean up on page unload
    // window.addEventListener('beforeunload', () => {
    //     if (statusCheckTimeout) {
    //         clearTimeout(statusCheckTimeout);
    //     }
    // });
})();