/*
    This script fetches and caches search suggestions to reduce server requests with an LRU cache.
*/
document.addEventListener('DOMContentLoaded', () => {
    const searchInput = document.getElementById('search-input');
    const searchWrapper = document.querySelector('.wrapper, .wrapper-results');
    const resultsWrapper = document.querySelector('.autocomplete');

    let suggestions = [];
    let currentIndex = -1;
    const cacheLimit = 10000; // This should take about 3.6 MB of memory
    const suggestionCache = new Map(); // Map to store suggestions with LRU capability

    // Fetch suggestions from server or cache
    async function getSuggestions(query) {
        if (suggestionCache.has(query)) {
            // Move the recently accessed item to the end of Map to mark it as most recently used
            const cachedResult = suggestionCache.get(query);
            suggestionCache.delete(query);
            suggestionCache.set(query, cachedResult);
            return cachedResult;
        }
        try {
            const response = await fetch(`/suggestions?q=${encodeURIComponent(query)}`);
            const data = await response.json();
            // Add result to cache and enforce cache limit
            suggestionCache.set(query, data[1]);
            if (suggestionCache.size > cacheLimit) {
                // Remove the oldest (first) item in the Map
                const firstKey = suggestionCache.keys().next().value;
                suggestionCache.delete(firstKey);
            }
            return data[1];
        } catch (error) {
            console.error('Error fetching suggestions:', error);
            return [];
        }
    }

    // Function to render results
    function renderSuggestions(results) {
        if (!results || !results.length) {
            searchWrapper.classList.remove('wrapper-searching');
            resultsWrapper.innerHTML = '';
            return;
        }

        let content = '';
        results.forEach((item, index) => {
            content += `<li data-index="${index}">${item}</li>`;
        });

        resultsWrapper.innerHTML = `<ul>${content}</ul>`;
        searchWrapper.classList.add('wrapper-searching');
    }

    // Fetch suggestions when input is focused
    searchInput.addEventListener('focus', async () => {
        const query = searchInput.value.trim();
        suggestions = await getSuggestions(query);
        renderSuggestions(suggestions);
        currentIndex = -1;
    });

    // Handle input event
    searchInput.addEventListener('input', async () => {
        const query = searchInput.value.trim();
        if (query.length > 0) {
            suggestions = await getSuggestions(query);
        } else {
            suggestions = [];
        }
        currentIndex = -1; // Reset index when new results come in
        renderSuggestions(suggestions);
    });

    // Handle keydown events for navigation
    searchInput.addEventListener('keydown', (event) => {
        const items = resultsWrapper.querySelectorAll('li');
        if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Tab') {
            event.preventDefault();
            if (items[currentIndex]) items[currentIndex].classList.remove('selected');

            currentIndex = event.key === 'ArrowUp'
                ? (currentIndex > 0 ? currentIndex - 1 : items.length - 1)
                : (currentIndex + 1) % items.length;

            if (items[currentIndex]) {
                items[currentIndex].classList.add('selected');
                searchInput.value = items[currentIndex].textContent;
            }
        } else if (event.key === 'Enter' && currentIndex > -1 && items[currentIndex]) {
            event.preventDefault();
            selectSuggestion(items[currentIndex]);
        }
    });

    // Function to handle suggestion selection
    function selectSuggestion(item) {
        const query = item.textContent;
        searchInput.value = query;
        resultsWrapper.innerHTML = '';
        searchWrapper.classList.remove('wrapper-searching');
    
        // Retrieve the `t` parameter from the hidden input or set a default
        const currentTemplateType = document.querySelector('input[name="t"]').value || 'web';
    
        // Redirect to the appropriate results page
        window.location.href = `/search?q=${encodeURIComponent(query)}&t=${encodeURIComponent(currentTemplateType)}`;
    }       

    // Handle clicks on search suggestions
    resultsWrapper.addEventListener('click', (event) => {
        if (event.target.tagName === 'LI') {
            selectSuggestion(event.target);
        }
    });

    // Close the suggestions when clicking outside
    document.addEventListener('click', (event) => {
        if (!searchWrapper.contains(event.target)) {
            searchWrapper.classList.remove('wrapper-searching');
            resultsWrapper.innerHTML = '';
            currentIndex = -1;
        }
    });
});