// Mapbox Globe Iteration 7: Timeline Animation for Online Education Growth
// Learning from: https://docs.mapbox.com/mapbox-gl-js/example/timeline-animation/
// Implementation: Range slider timeline control for temporal data exploration

// Mapbox access token
mapboxgl.accessToken = 'pk.eyJ1IjoibGludXhpc2Nvb2wiLCJhIjoiY2w3ajM1MnliMDV4NDNvb2J5c3V5dzRxZyJ9.wJukH5hVSiO74GM_VSJR3Q';

// Timeline years for the visualization
const years = ['2010', '2012', '2014', '2016', '2018', '2020', '2022', '2024'];
let currentYearIndex = 0;
let isPlaying = false;
let playInterval = null;

// Initialize the map with globe projection
const map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/dark-v11',
    projection: 'globe',
    center: [20, 20],
    zoom: 1.8,
    pitch: 20
});

// Process data: Transform yearData into separate features per year
// This is inspired by the timeline example's approach to preprocessing temporal data
function processTemporalData() {
    const processedFeatures = [];

    educationData.features.forEach(feature => {
        years.forEach((year, yearIndex) => {
            const yearStats = feature.properties.yearData[year];
            if (yearStats && yearStats.enrollment > 0) {
                processedFeatures.push({
                    type: 'Feature',
                    geometry: feature.geometry,
                    properties: {
                        name: feature.properties.name,
                        type: feature.properties.type,
                        country: feature.properties.country,
                        year: year,
                        yearIndex: yearIndex,
                        enrollment: yearStats.enrollment,
                        courses: yearStats.courses,
                        completionRate: yearStats.completionRate,
                        // Calculate growth metrics
                        growthRate: calculateGrowthRate(feature.properties.yearData, year, yearIndex)
                    }
                });
            }
        });
    });

    return {
        type: 'FeatureCollection',
        features: processedFeatures
    };
}

// Calculate year-over-year growth rate
function calculateGrowthRate(yearData, currentYear, yearIndex) {
    if (yearIndex === 0) return 0;

    const prevYear = years[yearIndex - 1];
    const currentEnrollment = yearData[currentYear].enrollment;
    const prevEnrollment = yearData[prevYear].enrollment;

    if (prevEnrollment === 0) return 100;

    return Math.round(((currentEnrollment - prevEnrollment) / prevEnrollment) * 100);
}

// Filter features by year index (inspired by timeline example's filterBy function)
function filterByYear(yearIndex) {
    map.setFilter('education-circles', ['==', 'yearIndex', yearIndex]);
    map.setFilter('education-labels', ['==', 'yearIndex', yearIndex]);

    // Update the timeline display
    document.getElementById('year-display').textContent = years[yearIndex];
    document.getElementById('year-slider').value = yearIndex;

    // Update statistics
    updateStatistics(yearIndex);
}

// Calculate and display aggregate statistics for the selected year
function updateStatistics(yearIndex) {
    const year = years[yearIndex];
    let totalEnrollment = 0;
    let totalCourses = 0;
    let platformCount = 0;
    let totalCompletionRate = 0;

    educationData.features.forEach(feature => {
        const yearStats = feature.properties.yearData[year];
        if (yearStats && yearStats.enrollment > 0) {
            totalEnrollment += yearStats.enrollment;
            totalCourses += yearStats.courses;
            platformCount++;
            totalCompletionRate += yearStats.completionRate;
        }
    });

    const avgCompletionRate = platformCount > 0 ? Math.round(totalCompletionRate / platformCount) : 0;

    document.getElementById('total-enrollment').textContent = formatNumber(totalEnrollment);
    document.getElementById('total-courses').textContent = formatNumber(totalCourses);
    document.getElementById('platform-count').textContent = platformCount;
    document.getElementById('avg-completion').textContent = avgCompletionRate + '%';
}

// Format large numbers for display
function formatNumber(num) {
    if (num >= 1000000) {
        return (num / 1000000).toFixed(1) + 'M';
    } else if (num >= 1000) {
        return (num / 1000).toFixed(1) + 'K';
    }
    return num.toString();
}

// Play/pause animation through timeline
function togglePlayback() {
    isPlaying = !isPlaying;
    const playButton = document.getElementById('play-button');

    if (isPlaying) {
        playButton.textContent = 'Pause';
        playInterval = setInterval(() => {
            currentYearIndex = (currentYearIndex + 1) % years.length;
            filterByYear(currentYearIndex);
        }, 1500); // Advance every 1.5 seconds
    } else {
        playButton.textContent = 'Play';
        if (playInterval) {
            clearInterval(playInterval);
            playInterval = null;
        }
    }
}

map.on('load', () => {
    // Configure globe atmosphere
    map.setFog({
        color: 'rgba(12, 20, 39, 0.9)',
        'high-color': 'rgba(36, 92, 223, 0.4)',
        'horizon-blend': 0.4,
        'space-color': '#000814',
        'star-intensity': 0.7
    });

    // Process temporal data
    const processedData = processTemporalData();

    // Add data source
    map.addSource('education-data', {
        type: 'geojson',
        data: processedData
    });

    // Add circle layer for education platforms
    // Size and color based on enrollment and growth
    map.addLayer({
        id: 'education-circles',
        type: 'circle',
        source: 'education-data',
        paint: {
            // Size based on enrollment
            'circle-radius': [
                'interpolate',
                ['exponential', 1.5],
                ['get', 'enrollment'],
                0, 3,
                1000000, 8,
                10000000, 14,
                50000000, 22,
                150000000, 32
            ],
            // Color based on growth rate
            'circle-color': [
                'interpolate',
                ['linear'],
                ['get', 'growthRate'],
                -50, '#d73027',  // Decline - red
                0, '#fee08b',    // No growth - yellow
                50, '#a6d96a',   // Moderate growth - light green
                100, '#1a9850',  // Strong growth - green
                200, '#0571b0'   // Exceptional growth - blue
            ],
            'circle-opacity': 0.85,
            'circle-stroke-width': 2,
            'circle-stroke-color': [
                'case',
                ['>=', ['get', 'enrollment'], 10000000], '#ffffff',
                'rgba(255, 255, 255, 0.5)'
            ]
        }
    });

    // Add labels for major platforms
    map.addLayer({
        id: 'education-labels',
        type: 'symbol',
        source: 'education-data',
        filter: ['>=', ['get', 'enrollment'], 5000000], // Only label platforms with 5M+ enrollments
        layout: {
            'text-field': ['get', 'name'],
            'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
            'text-size': 11,
            'text-offset': [0, 1.5],
            'text-anchor': 'top',
            'text-optional': true
        },
        paint: {
            'text-color': '#ffffff',
            'text-halo-color': '#000000',
            'text-halo-width': 1.5
        }
    });

    // Add popups on hover
    const popup = new mapboxgl.Popup({
        closeButton: false,
        closeOnClick: false,
        offset: 15
    });

    map.on('mouseenter', 'education-circles', (e) => {
        map.getCanvas().style.cursor = 'pointer';

        const props = e.features[0].properties;
        const coords = e.features[0].geometry.coordinates.slice();

        const html = `
            <div class="popup-content">
                <h3>${props.name}</h3>
                <p class="platform-type">${props.type} - ${props.country}</p>
                <div class="popup-stats">
                    <div class="stat">
                        <span class="stat-label">Year:</span>
                        <span class="stat-value">${props.year}</span>
                    </div>
                    <div class="stat">
                        <span class="stat-label">Enrollment:</span>
                        <span class="stat-value">${formatNumber(props.enrollment)}</span>
                    </div>
                    <div class="stat">
                        <span class="stat-label">Courses:</span>
                        <span class="stat-value">${formatNumber(props.courses)}</span>
                    </div>
                    <div class="stat">
                        <span class="stat-label">Completion Rate:</span>
                        <span class="stat-value">${props.completionRate}%</span>
                    </div>
                    <div class="stat">
                        <span class="stat-label">YoY Growth:</span>
                        <span class="stat-value growth-${props.growthRate >= 0 ? 'positive' : 'negative'}">
                            ${props.growthRate >= 0 ? '+' : ''}${props.growthRate}%
                        </span>
                    </div>
                </div>
            </div>
        `;

        popup.setLngLat(coords).setHTML(html).addTo(map);
    });

    map.on('mouseleave', 'education-circles', () => {
        map.getCanvas().style.cursor = '';
        popup.remove();
    });

    // Initialize timeline controls
    const slider = document.getElementById('year-slider');
    slider.min = 0;
    slider.max = years.length - 1;
    slider.value = 0;

    // Timeline slider event - manual scrubbing (learned from timeline example)
    slider.addEventListener('input', (e) => {
        if (isPlaying) {
            togglePlayback(); // Stop playback when manually scrubbing
        }
        currentYearIndex = parseInt(e.target.value);
        filterByYear(currentYearIndex);
    });

    // Play button event
    document.getElementById('play-button').addEventListener('click', togglePlayback);

    // Initialize with first year
    filterByYear(0);

    // Auto-rotate globe slowly
    let userInteracting = false;
    const rotationSpeed = 0.5; // degrees per frame

    map.on('mousedown', () => { userInteracting = true; });
    map.on('mouseup', () => { userInteracting = false; });
    map.on('dragend', () => { userInteracting = false; });
    map.on('pitchend', () => { userInteracting = false; });
    map.on('rotateend', () => { userInteracting = false; });

    function rotateGlobe() {
        if (!userInteracting && !isPlaying) {
            const center = map.getCenter();
            center.lng += rotationSpeed;
            map.setCenter(center);
        }
        requestAnimationFrame(rotateGlobe);
    }

    rotateGlobe();
});

// Add navigation controls
map.addControl(new mapboxgl.NavigationControl(), 'top-right');

// Add fullscreen control
map.addControl(new mapboxgl.FullscreenControl(), 'top-right');
