<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title th:text="#{page.title}">Reitti - Your Location Timeline</title>
    <link rel="icon" th:href="@{/img/logo.svg}">
    <link rel="apple-touch-icon" th:href="@{/img/logo.svg}">
    <link rel="shortcut icon" type="image/x-icon" th:href="@{/img/logo.svg}">
    <link rel="stylesheet" href="/css/leaflet.css">
    <link rel="stylesheet" href="/css/date-picker.css">
    <link rel="stylesheet" href="/css/main.css">
    <link rel="stylesheet" href="/css/lineicons.css">
    <link rel="stylesheet" href="/css/photo-client.css">
    <link rel="stylesheet" href="/css/inline-edit.css">
    <link rel="stylesheet" href="/css/avatar-marker.css">
    <link th:if="${userSettings.customCssUrl}" rel="stylesheet" th:href="${userSettings.customCssUrl}">
    <script src="/js/HumanizeDuration.js"></script>
    <script src="/js/horizontal-date-picker.js"></script>
    <script src="/js/timeline-scroll-indicator.js"></script>
    <script src="/js/photo-client.js"></script>
    <script src="/js/raw-location-loader.js"></script>
    <script src="/js/htmx.min.js"></script>
    <script src="/js/leaflet.js"></script>
    <script src="/js/TileLayer.Grayscale.js"></script>
    <script src="/js/leaflet.geodesic.2.7.2.js"></script>
</head>
<body>
<div id="message-container">
    <div id="sse-message"></div>
</div>
<div id="map"></div>

<!-- Auto-update overlay -->
<div id="auto-update-overlay" class="auto-update-overlay">
    <button sec:authorize="hasAnyRole('ROLE_ADMIN', 'ROLE_USER', 'ROLE_MAGIC_LINK_FULL_ACCESS')" class="overlay-button exit-button" onclick="disableAutoUpdate()" title="Exit Auto Update">
        <i class="lni lni-pause"></i>
    </button>
    <button class="overlay-button fullscreen-button" onclick="toggleFullscreen()" title="Toggle Fullscreen">
        <i class="lni lni-arrow-all-direction"></i>
    </button>
    <div class="date" id="auto-update-date"></div>
    <div class="time" id="auto-update-time"></div>
</div>

<div class="timeline">

    <div class="navbar">
        <span><img class="logo" th:src="@{/img/logo.svg}" alt="reitti logo" title="reitti" src="/img/logo.svg"></span>
        <a href="/" class="nav-link active" th:title="#{nav.timeline}"><i class="lni lni-route-1"></i></a>
        <a sec:authorize="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')" href="/memories" class="nav-link" th:title="#{nav.memories}"><i class="lni lni-agenda"></i></a>
        <a sec:authorize="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')" href="/statistics" class="nav-link" th:title="#{nav.statistics}"><i class="lni lni-bar-chart-4"></i></a>
        <a sec:authorize="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')" href="/settings" class="nav-link" th:title="#{nav.settings.tooltip}"><i class="lni lni-gear-1"></i></a>
        <a type="button" class="nav-link" id="auto-update-btn" onclick="toggleAutoUpdate()" title="Auto Update"><i class="lni lni-play"></i></a>
        <a type="button" class="nav-link" onclick="toggleFullscreen()" title="Toggle Fullscreen"><i class="lni lni-arrow-all-direction"></i></a>
        <form th:action="@{/logout}" method="post" >
            <button type="submit" class="nav-link" th:title="#{nav.logout.tooltip}"><i
                    class="lni lni-exit"></i>
            </button>
        </form>
    </div>
    <div class="timeline-container"
         hx-get="/timeline/content/range"
         hx-trigger="load, dateChanged from:body"
         hx-vals="js:{startDate: getTimelineParams().startDate, endDate: getTimelineParams().endDate, timezone: getTimelineParams().timezone}"
         hx-indicator="#loading-indicator">
        <div id="loading-indicator" class="timeline-entry" th:text="#{timeline.loading}">Loading...</div>
    </div>
    <button type="button" class="timeline-toggle-btn" id="timeline-toggle-btn" onclick="toggleTimeline()" title="Hide Timeline">
        <i class="lni lni-exit"></i>
    </button>
</div>

<button type="button" class="datepicker-toggle-btn" id="datepicker-toggle-btn" onclick="toggleDatePicker()" title="Hide Date Picker">
    <i class="lni lni-exit-down"></i>
</button>
<div id="horizontal-date-picker-container">

</div>

<script th:inline="javascript">
    // Locale object for JavaScript
    window.locale = {
        today: /*[[#{datepicker.today}]]*/ 'Today',
        days: [
            /*[[#{datepicker.days.sun}]]*/ 'Sun',
            /*[[#{datepicker.days.mon}]]*/ 'Mon',
            /*[[#{datepicker.days.tue}]]*/ 'Tue',
            /*[[#{datepicker.days.wed}]]*/ 'Wed',
            /*[[#{datepicker.days.thu}]]*/ 'Thu',
            /*[[#{datepicker.days.fri}]]*/ 'Fri',
            /*[[#{datepicker.days.sat}]]*/ 'Sat'
        ],
        months: [
            /*[[#{datepicker.months.jan}]]*/ 'Jan',
            /*[[#{datepicker.months.feb}]]*/ 'Feb',
            /*[[#{datepicker.months.mar}]]*/ 'Mar',
            /*[[#{datepicker.months.apr}]]*/ 'Apr',
            /*[[#{datepicker.months.may}]]*/ 'May',
            /*[[#{datepicker.months.jun}]]*/ 'Jun',
            /*[[#{datepicker.months.jul}]]*/ 'Jul',
            /*[[#{datepicker.months.aug}]]*/ 'Aug',
            /*[[#{datepicker.months.sep}]]*/ 'Sep',
            /*[[#{datepicker.months.oct}]]*/ 'Oct',
            /*[[#{datepicker.months.nov}]]*/ 'Nov',
            /*[[#{datepicker.months.dec}]]*/ 'Dec'
        ],
        sse: {
            error: /*[[#{sse.error.connection-lost}]]*/ 'Connection to server lost! Will reconnect ...',
        },
        autoupdate: {
          latestLocation:  /*[[#{map.auto-update.latest-location}]]*/ 'Latest location',
        }
    };

    window.userSettings = /*[[${userSettings}]]*/ {}

    const messagesDiv = document.getElementById('sse-message');
    let autoUpdateMode = false;
    let autoUpdateTimer = null;
    let autoUpdateTimeInterval = null;
    let eventSource = null;
    let reloadTimeoutId = null;
    let maxWaitTimeoutId = null;
    let pendingEvents = [];
    let firstEventTime = null;
    let reconnectTimeoutId = null;

    // Store current date range selection
    let currentDateRange = null;

    // Initialize the map
    const map = L.map('map', {zoomControl: false, attributionControl: false}).setView([window.userSettings.homeLatitude, window.userSettings.homeLongitude], 12);

    // Initialize raw location loader
    let rawLocationLoader;

    function getSelectedDate() {
        const urlParams = new URLSearchParams(window.location.search);
        if (urlParams.has('date')) {
            return urlParams.get('date');
        } else if (window.userSettings.uiMode === 'SHARED_LIVE_MODE_ONLY') {
            return getCurrentLocalDate();
        } else if (window.userSettings.newestData) {
            return window.userSettings.newestData.split('T')[0];
        } else {
            return getCurrentLocalDate();
        }
    }

    function getUserTimezone() {
        if (window.userSettings.timezoneOverride) {
            return window.userSettings.timezoneOverride;
        } else {
            return Intl.DateTimeFormat().resolvedOptions().timeZone;
        }
    }

    function getTimelineParams() {
        const timezone = getUserTimezone();
        if (currentDateRange && currentDateRange.startDate && currentDateRange.endDate) {
            // Range mode - use actual range
            return {
                startDate: currentDateRange.startDate,
                endDate: currentDateRange.endDate,
                timezone: timezone
            };
        } else {
            // Single date mode - use same date for both start and end
            const selectedDate = getSelectedDate();
            return {
                startDate: selectedDate,
                endDate: selectedDate,
                timezone: timezone
            };
        }
    }


    function selectUser(userHeader) {
        // Remove active class from all user headers
        document.querySelectorAll('.user-header').forEach(header => {
            header.classList.remove('active');
        });

        // Add active class to clicked user header
        userHeader.classList.add('active');

        // Get the user ID from the clicked header
        const userId = userHeader.getAttribute('data-user-id');

        // Hide all user timeline sections
        document.querySelectorAll('.user-timeline-section').forEach(section => {
            section.classList.remove('active');
        });

        // Show the corresponding user timeline section
        const targetSection = document.querySelector(`.user-timeline-section[data-user-id="${userId}"]`);
        if (targetSection) {
            targetSection.classList.add('active');
        }
    }

    // Timeline visibility functions
    function toggleTimeline() {
        const body = document.body;
        const isHidden = body.classList.contains('timeline-hidden');
        
        if (isHidden) {
            body.classList.remove('timeline-hidden');
            localStorage.setItem('timelineHidden', 'false');
        } else {
            // Scroll timeline back to top before hiding to ensure navbar is accessible
            const timeline = document.querySelector('.timeline');
            if (timeline) {
                timeline.scrollTop = 0;
            }
            body.classList.add('timeline-hidden');
            localStorage.setItem('timelineHidden', 'true');
        }
        
        updateTimelineToggleButton();
    }
    
    function updateTimelineToggleButton() {
        const btn = document.getElementById('timeline-toggle-btn');
        const icon = btn.querySelector('i');
        const isHidden = document.body.classList.contains('timeline-hidden');
        
        if (isHidden) {
            icon.className = 'lni lni-enter';
            btn.title = 'Show Timeline';
        } else {
            icon.className = 'lni lni-exit';
            btn.title = 'Hide Timeline';
        }
    }
    
    // Restore timeline visibility state from localStorage
    function restoreTimelineState() {
        const timelineHidden = localStorage.getItem('timelineHidden');
        if (timelineHidden === 'true') {
            document.body.classList.add('timeline-hidden');
        }
        updateTimelineToggleButton();
    }
    
    // Date picker visibility functions
    function toggleDatePicker() {
        const body = document.body;
        const isHidden = body.classList.contains('datepicker-hidden');
        
        if (isHidden) {
            body.classList.remove('datepicker-hidden');
            localStorage.setItem('datepickerHidden', 'false');
        } else {
            body.classList.add('datepicker-hidden');
            localStorage.setItem('datepickerHidden', 'true');
        }
        
        updateDatePickerToggleButton();
    }
    
    function updateDatePickerToggleButton() {
        const btn = document.getElementById('datepicker-toggle-btn');
        const icon = btn.querySelector('i');
        const isHidden = document.body.classList.contains('datepicker-hidden');
        
        if (isHidden) {
            icon.className = 'lni lni-exit-up';
            btn.title = 'Show Date Picker';
        } else {
            icon.className = 'lni lni-enter-down';
            btn.title = 'Hide Date Picker';
        }
    }
    
    // Restore date picker visibility state from localStorage
    function restoreDatePickerState() {
        const datepickerHidden = localStorage.getItem('datepickerHidden');
        if (datepickerHidden === 'true') {
            document.body.classList.add('datepicker-hidden');
        }
        updateDatePickerToggleButton();
    }

    document.addEventListener('DOMContentLoaded', function () {
        // Restore timeline state on page load
        restoreTimelineState();
        // Restore date picker state on page load
        restoreDatePickerState();
        // Check if date is in URL parameters
        const urlParams = new URLSearchParams(window.location.search);
        let initialDate;

        if (urlParams.has('date')) {
            initialDate = urlParams.get('date');
            // Validate date format (YYYY-MM-DD)
            if (!/^\d{4}-\d{2}-\d{2}$/.test(initialDate)) {
                initialDate = null;
            }
        }

        if (!initialDate) {
            if (window.userSettings.uiMode === 'SHARED_LIVE_MODE_ONLY') {

            } else if (window.userSettings.newestData) {
                initialDate = window.userSettings.newestData.split('T')[0]
            }
        }

        // Set date picker to URL date or today's date
        const formattedDate = initialDate || getCurrentLocalDate();

        // Function to update URL with date parameter
        function updateUrlWithDate(date) {
            const url = new URL(window.location);
            url.searchParams.set('date', date);
            window.history.pushState({}, '', url);
        }


        const tilesUrl = window.userSettings.tiles.service;
        const tilesAttribution = window.userSettings.tiles.attribution;

        const tileLayer = window.userSettings.preferColoredMap ? L.tileLayer : L.tileLayer.grayscale;
        tileLayer(tilesUrl, {
            maxZoom: 19,
            attribution:  tilesAttribution
        }).addTo(map);
        L.control.attribution({position: 'topright'}).addAttribution(tilesAttribution)
            .addTo(map)

        // Initialize photo client
        const photoClient = new PhotoClient(map, window.userSettings.photoMode === 'ENABLED');
        
        // Initialize raw location loader
        rawLocationLoader = new RawLocationLoader(map, window.userSettings, {
            paddingTopLeft: [100,0],
            paddingBottomRight: [100, 300],
            zoomSnap: 0.1
        });

        // Initialize raw location loader with user configurations
        initializeRawLocationLoader();

        // Listen for map move/zoom events to update photo markers
        map.on('moveend zoomend', () => {
            photoClient.onMapMoveEnd();
        });

        function loadTimelineData(startDate, endDate) {
            if (startDate && endDate && startDate !== endDate) {
                // Range mode
                photoClient.updatePhotosForRange(startDate, endDate, getUserTimezone());
            } else {
                const date = startDate || getSelectedDate();
                photoClient.updatePhotosForRange(date, date, getUserTimezone());
            }
            
            // Load raw location data using the loader
            rawLocationLoader.loadForDateRange(autoUpdateMode, false);
        }

        const selectedPath = L.geodesic([], {
            color: '#ff984f',
            weight: 6,
            opacity: 1,
            lineJoin: 'round',
            lineCap: 'round',
            steps: 2

        });


        // Function to initialize raw location loader with user configurations
        function initializeRawLocationLoader() {
            const userConfigs = [];
            const timelineContainers = document.querySelectorAll('.user-timeline-section');

            timelineContainers.forEach(container => {
                const config = {
                    respectBounds: true,
                    url: container.dataset.rawLocationPointsUrl,
                    color: container.dataset.baseColor,
                    avatarUrl: container.dataset.userAvatarUrl,
                    avatarFallback: container.dataset.avatarFallback,
                    displayName: container.dataset.displayName
                };
                userConfigs.push(config);
            });

            rawLocationLoader.init(userConfigs);
        }

        // Add HTMX event handlers for timeline updates
        document.body.addEventListener('htmx:afterSwap', function(event) {
            if (event.detail.target.classList.contains('timeline-container')) {
                // Re-initialize raw location loader with updated user configurations
                initializeRawLocationLoader();

                // Timeline content has been updated, update map markers
                const params = getTimelineParams();
                loadTimelineData(params.startDate, params.endDate);
                updateMapFromTimeline();
                // Initialize scroll indicator after timeline is updated
                if (window.timelineScrollIndicator) {
                    window.timelineScrollIndicator.cleanup();
                }
                window.timelineScrollIndicator = new TimelineScrollIndicator();
                window.timelineScrollIndicator.init();
            }
        });
        // Function to update map markers from timeline entries
        function updateMapFromTimeline() {
            const bounds = L.latLngBounds();

            // Clear existing markers and paths (except tile layer)
            map.eachLayer(layer => {
                if (!layer._url) {
                    map.removeLayer(layer);
                }
            });

            let hasValidCoords = false;

            // Group places by coordinates to avoid duplicate markers

            let timelineUserSections = document.querySelectorAll('.user-timeline-section ');

            for (const timelineUserSection of timelineUserSections) {
                const color = timelineUserSection?.dataset.baseColor;
                const timelineEntries = timelineUserSection.querySelectorAll('.timeline-entry[data-lat][data-lng]');

                const placeGroups = new Map();

                timelineEntries.forEach(entryElement => {
                    const lat = parseFloat(entryElement.dataset.lat);
                    const lng = parseFloat(entryElement.dataset.lng);

                    if (!isNaN(lat) && !isNaN(lng) && entryElement.classList.contains('visit')) {
                        const coordKey = `${lat.toFixed(6)},${lng.toFixed(6)}`;

                        if (!placeGroups.has(coordKey)) {
                            // Extract place name from the timeline entry
                            const placeNameElement = entryElement.querySelector('.place-name');
                            const placeName = placeNameElement ? placeNameElement.textContent : 'Unknown Place';

                            placeGroups.set(coordKey, {
                                lat: lat,
                                lng: lng,
                                totalDurationMs: 0,
                                visits: [],
                                place: { name: placeName, address: '' }
                            });
                        }

                        const group = placeGroups.get(coordKey);
                        // Calculate duration from time range text
                        const durationElement = entryElement.querySelector('.entry-duration');
                        if (durationElement) {
                            const durationText = durationElement.textContent;
                            const durationMs = parseDurationText(durationText);
                            group.totalDurationMs += durationMs;
                        }
                        group.visits.push({ id: entryElement.dataset.id });

                        bounds.extend([lat, lng]);
                        hasValidCoords = true;
                    }


                    // Draw markers for grouped places
                    placeGroups.forEach((group) => {
                        const { lat, lng, totalDurationMs, visits, place } = group;

                        // Calculate radius using logarithmic scale
                        const durationHours = totalDurationMs / (1000 * 60 * 60);
                        const baseRadius = 15;
                        const maxRadius = 100;
                        const minRadius = 15;

                        const logScale = Math.log(1 + durationHours) / Math.log(1 + 24);
                        const radius = Math.min(maxRadius, Math.max(minRadius, baseRadius + (logScale * (maxRadius - baseRadius))));

                        // Create marker
                        L.circleMarker([lat, lng], {
                            radius: 5,
                            fillColor: color ? color : '#ff6c00',
                            color: '#fff',
                            weight: 1,
                            opacity: 1,
                            fillOpacity: 0.8
                        }).addTo(map);

                        // Create circle with calculated radius
                        const circle = L.circle([lat, lng], {
                            color: color ? color : '#dcae4a',
                            fillColor: '#ff984f',
                            fillOpacity: 0.1,
                            radius: radius
                        }).addTo(map);

                        const totalDurationText = humanizeDuration(totalDurationMs, {units: ["h", "m"], round: true});
                        const visitCount = visits.length;
                        const visitText = visitCount === 1 ? 'visit' : 'visits';

                        let tooltip = L.tooltip([lat, lng], {
                            content: `<div class="visit-title">${place.name}</div>
                             <div class="visit-description">
                                 ${visitCount} ${visitText} - Total: ${totalDurationText}
                             </div>`,
                            className: 'visit-popup',
                            permanent: false
                        });

                        bounds.extend([lat, lng])

                        circle.bindTooltip(tooltip);
                    });
                });

            }
            return bounds;
        }

        // Helper function to parse duration text (simple implementation)
        function parseDurationText(durationText) {
            // Extract numbers followed by 'h' or 'm'
            const hours = (durationText.match(/(\d+)h/) || [0, 0])[1];
            const minutes = (durationText.match(/(\d+)m/) || [0, 0])[1];
            return (parseInt(hours) * 60 + parseInt(minutes)) * 60 * 1000; // Convert to milliseconds
        }

        // Handle clicks on timeline entries
        document.querySelector('.timeline-container').addEventListener('click', function (event) {
            const entry = event.target.closest('.timeline-entry');
            if (!entry) return;

            const editingElement = event.target.closest('.editing');
            if (editingElement || event.target.classList.contains('edit-icon')) {
                return;
            }
            // Check if this entry is already active (deselection case)
            const isCurrentlyActive = entry.classList.contains('active');
            
            // Remove active class from all entries
            document.querySelectorAll('.timeline-container .timeline-entry')
                .forEach(e => e.classList.remove('active'));
            
            // Remove any selected path
            selectedPath.remove();
            
            if (isCurrentlyActive) {
                // Deselection: zoom back to original bounds showing all data
                if (window.originalBounds && window.originalBounds.isValid()) {
                    map.flyToBounds(window.originalBounds, rawLocationLoader.fitToBoundsConfig);
                }
            } else {
                // Selection: zoom to specific entry
                entry.classList.add('active');
                const newBounds = L.latLngBounds();

                const lat = parseFloat(entry.dataset.lat);
                const lng = parseFloat(entry.dataset.lng);

                if (entry.dataset.path) {
                    const pathData = JSON.parse(entry.dataset.path);
                    const latlngs = pathData.map(coord => [coord.latitude, coord.longitude]);
                    latlngs.forEach(latlng => {
                        newBounds.extend(latlng);
                    });
                    selectedPath.setLatLngs(latlngs);
                    selectedPath.addTo(map);
                }
                    
                if (!isNaN(lat) && !isNaN(lng)) {
                    newBounds.extend([lat, lng]);
                }

                if (newBounds.isValid()) {
                    map.flyToBounds(newBounds, rawLocationLoader.fitToBoundsConfig);
                }
            }
        });

        loadTimelineData(formattedDate, formattedDate);

        // Parse the initial date properly to ensure correct date picker initialization
        let dateToUse = new Date();
        if (initialDate) {
            // Parse the date from URL parameter (YYYY-MM-DD format)
            const [year, month, day] = initialDate.split('-').map(Number);
            // Note: month is 0-indexed in JavaScript Date
            dateToUse = new Date(year, month - 1, day);
        }

        // Initialize horizontal date picker
        window.horizontalDatePicker = new HorizontalDatePicker({
            container: document.getElementById('horizontal-date-picker-container'),
            selectedDate: dateToUse,
            showNavButtons: false,
            daysToShow: 21,
            showMonthRow: true,
            showYearRow: true,
            yearsToShow: 5,
            allowFutureDates: false,
            showTodayButton: true,
            onDateSelect: (date, formattedDate) => {
                // Update URL
                updateUrlWithDate(formattedDate);
                // Clear any existing date range
                currentDateRange = null;
                // Trigger HTMX reload of timeline
                document.body.dispatchEvent(new CustomEvent('dateChanged'));
            },
            onDateRangeSelect: (startDate, endDate, formattedStartDate, formattedEndDate) => {
                // Store the date range
                currentDateRange = {
                    startDate: formattedStartDate,
                    endDate: formattedEndDate
                };
                // Update URL to show range
                const url = new URL(window.location);
                url.searchParams.set('startDate', formattedStartDate);
                url.searchParams.set('endDate', formattedEndDate);
                url.searchParams.delete('date');
                window.history.pushState({}, '', url);
                // Trigger HTMX reload of timeline
                document.body.dispatchEvent(new CustomEvent('dateChanged'));
            }
        });
    });


    if (window.userSettings.uiMode === "SHARED_LIVE_MODE_ONLY") {
        toggleAutoUpdate();
    }
    function toggleAutoUpdate() {
        const btn = document.getElementById('auto-update-btn');
        const icon = btn.querySelector('i');
        
        if (!autoUpdateMode) {
            document.body.classList.add('auto-update-mode');

            // Enable auto-update mode
            autoUpdateMode = true;
            icon.className = 'lni lni-pause';
            btn.title = 'Pause Auto Update';

            // Hide timeline and date picker smoothly
            hideUIElements();
            
            // Show auto-update overlay
            showAutoUpdateOverlay();
            
            // Update the date picker to today
            if (window.horizontalDatePicker) {
                window.horizontalDatePicker.setDate(new Date());
            }

            // Start the timer to check for date changes every 30 seconds
            startAutoUpdateTimer();

            // Connect to SSE with automatic reconnection
            connectSSE();

        } else {
            // Disable auto-update mode
            disableAutoUpdate();
        }
    }

    function disableAutoUpdate() {
        autoUpdateMode = false;
        
        // Clear the timer
        if (autoUpdateTimer) {
            clearInterval(autoUpdateTimer);
            autoUpdateTimer = null;
        }
        
        // Clear time update interval
        if (autoUpdateTimeInterval) {
            clearInterval(autoUpdateTimeInterval);
            autoUpdateTimeInterval = null;
        }
        
        // Clear any pending reload timeout
        if (reloadTimeoutId) {
            clearTimeout(reloadTimeoutId);
            reloadTimeoutId = null;
        }
        
        // Clear max wait timeout
        if (maxWaitTimeoutId) {
            clearTimeout(maxWaitTimeoutId);
            maxWaitTimeoutId = null;
        }
        
        // Clear pending events
        pendingEvents = [];
        firstEventTime = null;
        
        // Clear reconnect timeout
        if (reconnectTimeoutId) {
            clearTimeout(reconnectTimeoutId);
            reconnectTimeoutId = null;
        }
        
        if (eventSource) {
            eventSource.close();
            eventSource = null;
        }
        
        rawLocationLoader.removePulsatingMarkers();
        
        // Hide auto-update overlay
        hideAutoUpdateOverlay();
        
        // Show timeline and date picker again
        showUIElements();
        
        const btn = document.getElementById('auto-update-btn');
        const icon = btn.querySelector('i');
        icon.className = 'lni lni-play';
        btn.title = 'Auto Update';
        if (window.horizontalDatePicker) {
            window.horizontalDatePicker.exitRangeMode();
            window.horizontalDatePicker.setDate(getSelectedDate());
        }

        document.body.classList.remove('auto-update-mode');

    }

    function startAutoUpdateTimer() {
        // Check every 30 seconds if we need to switch to today's date
        autoUpdateTimer = setInterval(() => {
            if (!autoUpdateMode) {
                return; // Exit if auto-update mode was disabled
            }
            
            // If the selected date is not today, switch to today
            if (!isSelectedDateToday()) {
                console.log('Auto-update: Switching to today\'s date');
                if (window.horizontalDatePicker) {
                    window.horizontalDatePicker.setDate(new Date());
                }
            }
        }, 30000); // 30 seconds
    }

    function isSelectedDateToday() {
        const today = getCurrentLocalDate();
        const selectedDate = getSelectedDate();
        return selectedDate === today;
    }


    function scheduleTimelineReload(eventData) {
        // Add event to pending events
        pendingEvents.push(eventData);
        
        if (firstEventTime === null) {
            firstEventTime = Date.now();
            
            // Set maximum wait timeout (30 seconds from first event)
            maxWaitTimeoutId = setTimeout(() => {
                if (autoUpdateMode && pendingEvents.length > 0) {
                    console.log(`Auto-update: Reloading timeline data after max wait time (30s) with ${pendingEvents.length} accumulated events`);
                    executeTimelineReload();
                }
            }, 30000);
        }
        
        if (reloadTimeoutId) {
            clearTimeout(reloadTimeoutId);
        }
        
        reloadTimeoutId = setTimeout(() => {
            if (autoUpdateMode && pendingEvents.length > 0) {
                console.log(`Auto-update: Reloading timeline data after 5s settle time with ${pendingEvents.length} accumulated events`);
                executeTimelineReload();
            }
        }, 5000);
    }
    
    function executeTimelineReload() {
        // Clear all timeouts
        if (reloadTimeoutId) {
            clearTimeout(reloadTimeoutId);
            reloadTimeoutId = null;
        }
        if (maxWaitTimeoutId) {
            clearTimeout(maxWaitTimeoutId);
            maxWaitTimeoutId = null;
        }
        
        // Reload timeline
        document.body.dispatchEvent(new CustomEvent('dateChanged'));
        
        // Clear pending events and reset first event time
        pendingEvents = [];
        firstEventTime = null;
    }

    function connectSSE() {
        if (!autoUpdateMode) {
            return; // Don't connect if auto-update is disabled
        }

        console.log('Connecting to SSE...');
        eventSource = new EventSource('/events');

        eventSource.onopen = function() {
            console.log('SSE connection opened.');
            messagesDiv.innerHTML = ''; // Clear any error messages
            messagesDiv.classList.remove('active');
            
            // Clear any pending reconnect timeout since we're connected
            if (reconnectTimeoutId) {
                clearTimeout(reconnectTimeoutId);
                reconnectTimeoutId = null;
            }
        };

        eventSource.onerror = function(error) {
            console.error('EventSource failed:', error);
            messagesDiv.innerHTML = `<p><strong>${window.locale.sse.error}</strong></p>`;
            messagesDiv.classList.add('active');
            
            // Close the current connection
            if (eventSource) {
                eventSource.close();
                eventSource = null;
            }
            
            // Schedule reconnection after 5 seconds if still in auto-update mode
            if (autoUpdateMode && !reconnectTimeoutId) {
                console.log('Scheduling SSE reconnection in 5 seconds...');
                reconnectTimeoutId = setTimeout(() => {
                    reconnectTimeoutId = null;
                    connectSSE();
                }, 5000);
            }
        };

        eventSource.onmessage = function(event) {
            console.log('Received generic event:', event.data);
            
            // Clear error messages on successful message receipt (fallback for onopen)
            if (messagesDiv.classList.contains('active')) {
                messagesDiv.innerHTML = '';
                messagesDiv.classList.remove('active');
            }
            
            // Clear any pending reconnect timeout since we're receiving messages
            if (reconnectTimeoutId) {
                clearTimeout(reconnectTimeoutId);
                reconnectTimeoutId = null;
            }
            
            // Parse the event data
            try {
                const eventData = JSON.parse(event.data);
                
                // Check if the event has a date field and it matches today
                if (eventData.date) {
                    const today = getCurrentLocalDate(); // YYYY-MM-DD format
                    const eventDate = eventData.date;
                    
                    // If event date matches today and we're in auto-update mode, schedule reload
                    if (eventDate === today && autoUpdateMode) {
                        console.log('Auto-update: Scheduling timeline reload due to SSE event for today');
                        scheduleTimelineReload(eventData);
                    }
                }
            } catch (error) {
                console.warn('Could not parse SSE event data:', error);
            }
        };
    }

    function hideUIElements() {
        const timeline = document.querySelector('.timeline');
        const datePicker = document.getElementById('horizontal-date-picker-container');

        timeline.classList.add('hidden');
        datePicker.classList.add('hidden');
    }

    function showUIElements() {
        const timeline = document.querySelector('.timeline');
        const datePicker = document.getElementById('horizontal-date-picker-container');
        
        timeline.classList.remove('hidden');
        datePicker.classList.remove('hidden');
    }

    function showAutoUpdateOverlay() {
        const overlay = document.getElementById('auto-update-overlay');
        
        // Update initial time
        updateAutoUpdateTime();
        
        // Show overlay
        overlay.classList.add('visible');
        
        // Start updating time every second
        autoUpdateTimeInterval = setInterval(updateAutoUpdateTime, 1000);
    }

    function hideAutoUpdateOverlay() {
        const overlay = document.getElementById('auto-update-overlay');
        overlay.classList.remove('visible');
    }

    function updateAutoUpdateTime() {
        const now = new Date();
        const dateElement = document.getElementById('auto-update-date');
        const timeElement = document.getElementById('auto-update-time');
        
        // Use browser locale for date formatting
        const dateOptions = { 
            weekday: 'long', 
            year: 'numeric', 
            month: 'long', 
            day: 'numeric' 
        };
        const formattedDate = now.toLocaleDateString(navigator.language, dateOptions);
        
        // Use browser locale for time formatting
        const timeOptions = { 
            hour: '2-digit', 
            minute: '2-digit',
            hour12: false
        };
        const formattedTime = now.toLocaleTimeString(navigator.language, timeOptions);
        
        dateElement.textContent = formattedDate;
        timeElement.textContent = formattedTime;
    }

    function toggleFullscreen() {
        if (!document.fullscreenElement) {
            document.documentElement.requestFullscreen().catch(err => {
                console.log(`Error attempting to enable fullscreen: ${err.message}`);
            });
        } else {
            document.exitFullscreen();
        }
    }
</script>
</body>
</html>
