// Mapbox Globe Visualization 5: Global Educational Institutions
// Demonstrates data-driven styling with match expressions for categorical data
// and interpolate expressions for continuous educational metrics

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

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

// Auto-rotation state
let userInteracting = false;
let rotationActive = false;  // Auto-rotation disabled

// Track current styling metric
let currentSizeMetric = 'enrollment';
let currentColorMetric = 'quality';

map.on('load', () => {
    // Configure globe atmosphere
    map.setFog({
        color: 'rgba(20, 30, 50, 0.9)',
        'high-color': 'rgba(50, 80, 150, 0.5)',
        'horizon-blend': 0.05,
        'space-color': 'rgba(5, 5, 15, 1)',
        'star-intensity': 0.7
    });

    // Add educational institutions data source
    map.addSource('education', {
        type: 'geojson',
        data: educationData
    });

    // Main institution layer - using MATCH expression for categorical type styling
    // and INTERPOLATE for continuous quality metrics
    // This demonstrates the data-driven styling learned from Mapbox documentation
    map.addLayer({
        id: 'institutions',
        type: 'circle',
        source: 'education',
        paint: {
            // SIZE: Interpolate based on enrollment (continuous data)
            'circle-radius': [
                'interpolate',
                ['linear'],
                ['get', 'enrollment'],
                1000, 4,        // Small institutions
                10000, 7,
                30000, 11,
                60000, 16,
                100000, 22,
                350000, 30      // Massive universities
            ],

            // COLOR: Interpolate based on quality score (continuous data)
            // Uses a diverging-like scale from red (low quality) to gold (high quality)
            'circle-color': [
                'interpolate',
                ['linear'],
                ['get', 'quality'],
                50, '#8b0000',   // Dark red - very low quality
                60, '#dc143c',   // Crimson - low quality
                70, '#ff6347',   // Tomato - below average
                75, '#ff8c00',   // Dark orange - average
                80, '#ffa500',   // Orange - above average
                85, '#ffd700',   // Gold - good
                90, '#00ced1',   // Dark turquoise - very good
                95, '#00bfff',   // Deep sky blue - excellent
                100, '#1e90ff'   // Dodger blue - world class
            ],

            // OPACITY: Zoom-responsive for better visibility
            'circle-opacity': [
                'interpolate',
                ['linear'],
                ['zoom'],
                1, 0.75,
                4, 0.85,
                8, 0.95
            ],

            // STROKE: Categorical styling using MATCH expression
            // This is the key technique learned from the web source
            'circle-stroke-color': [
                'match',
                ['get', 'type'],
                'University', '#ffffff',
                'School', '#cccccc',
                '#999999'  // default
            ],

            'circle-stroke-width': [
                'interpolate',
                ['linear'],
                ['zoom'],
                1, 0.5,
                4, 1,
                8, 2
            ]
        }
    });

    // Labels layer for top-tier institutions (quality >= 85)
    map.addLayer({
        id: 'institution-labels',
        type: 'symbol',
        source: 'education',
        filter: ['>=', ['get', 'quality'], 85],
        layout: {
            'text-field': ['get', 'name'],
            'text-size': [
                'interpolate',
                ['linear'],
                ['get', 'quality'],
                85, 10,
                100, 14
            ],
            'text-offset': [0, 1.5],
            'text-anchor': 'top',
            'text-max-width': 8
        },
        paint: {
            'text-color': '#ffffff',
            'text-halo-color': '#000000',
            'text-halo-width': 1.5,
            'text-opacity': [
                'interpolate',
                ['linear'],
                ['zoom'],
                1, 0,
                3, 0.6,
                6, 1
            ]
        },
        minzoom: 3
    });

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

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

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

        const html = `
            <div style="font-family: 'Inter', sans-serif; min-width: 200px;">
                <h3 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 600; color: #1e90ff;">
                    ${props.name}
                </h3>
                <div style="font-size: 12px; color: #ccc; line-height: 1.6;">
                    <div><strong>Country:</strong> ${props.country}</div>
                    <div><strong>Type:</strong> ${props.type}</div>
                    <div style="margin-top: 6px; padding-top: 6px; border-top: 1px solid #444;">
                        <strong>Quality Score:</strong> ${props.quality}/100
                    </div>
                    <div><strong>Enrollment:</strong> ${props.enrollment.toLocaleString()}</div>
                    <div><strong>Literacy Rate:</strong> ${props.literacy}%</div>
                    <div><strong>Funding:</strong> $${props.funding}M USD</div>
                </div>
            </div>
        `;

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

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

    // Start auto-rotation
    startRotation();

    // Update statistics panel
    updateStatistics();
});

// Auto-rotation function
function startRotation() {
    if (!rotationActive || userInteracting) return;

    const center = map.getCenter();
    center.lng -= 0.08; // Slower rotation for educational theme

    map.easeTo({
        center: center,
        duration: 1000,
        easing: (t) => t
    });
}

// Rotation loop
map.on('moveend', () => {
    if (rotationActive) {
        startRotation();
    }
});

// Pause rotation on user interaction
map.on('mousedown', () => { userInteracting = true; });
map.on('mouseup', () => {
    userInteracting = false;
    if (rotationActive) startRotation();
});
map.on('dragstart', () => { userInteracting = true; });
map.on('dragend', () => {
    userInteracting = false;
    if (rotationActive) startRotation();
});
map.on('pitchstart', () => { userInteracting = true; });
map.on('pitchend', () => {
    userInteracting = false;
    if (rotationActive) startRotation();
});

// Toggle rotation
document.getElementById('toggle-rotation').addEventListener('click', () => {
    rotationActive = !rotationActive;
    document.getElementById('toggle-rotation').textContent =
        rotationActive ? 'Pause Rotation' : 'Resume Rotation';
    if (rotationActive) startRotation();
});

// Reset view
document.getElementById('reset-view').addEventListener('click', () => {
    map.flyTo({
        center: [15, 25],
        zoom: 1.8,
        pitch: 0,
        bearing: 0,
        duration: 2000
    });
});

// Metric switching - demonstrates dynamic expression updates
document.getElementById('size-metric').addEventListener('change', (e) => {
    currentSizeMetric = e.target.value;
    updateCircleSize();
    updateLegend();
});

document.getElementById('color-metric').addEventListener('change', (e) => {
    currentColorMetric = e.target.value;
    updateCircleColor();
    updateLegend();
});

// Update circle size based on selected metric
function updateCircleSize() {
    const sizeExpressions = {
        enrollment: [
            'interpolate',
            ['linear'],
            ['get', 'enrollment'],
            1000, 4,
            10000, 7,
            30000, 11,
            60000, 16,
            100000, 22,
            350000, 30
        ],
        quality: [
            'interpolate',
            ['linear'],
            ['get', 'quality'],
            50, 4,
            60, 6,
            70, 9,
            80, 13,
            90, 18,
            100, 26
        ],
        literacy: [
            'interpolate',
            ['linear'],
            ['get', 'literacy'],
            40, 4,
            60, 8,
            75, 12,
            90, 17,
            100, 24
        ],
        funding: [
            'interpolate',
            ['linear'],
            ['get', 'funding'],
            200, 4,
            500, 7,
            1000, 10,
            2000, 14,
            3500, 19,
            5500, 28
        ]
    };

    map.setPaintProperty('institutions', 'circle-radius', sizeExpressions[currentSizeMetric]);
}

// Update circle color based on selected metric
function updateCircleColor() {
    const colorExpressions = {
        quality: [
            'interpolate',
            ['linear'],
            ['get', 'quality'],
            50, '#8b0000',
            60, '#dc143c',
            70, '#ff6347',
            75, '#ff8c00',
            80, '#ffa500',
            85, '#ffd700',
            90, '#00ced1',
            95, '#00bfff',
            100, '#1e90ff'
        ],
        literacy: [
            'interpolate',
            ['linear'],
            ['get', 'literacy'],
            40, '#8b0000',
            50, '#dc143c',
            65, '#ff6347',
            75, '#ffa500',
            85, '#ffd700',
            92, '#00ced1',
            97, '#00bfff',
            100, '#1e90ff'
        ],
        enrollment: [
            'interpolate',
            ['linear'],
            ['get', 'enrollment'],
            1000, '#4a148c',     // Deep purple - small
            10000, '#7b1fa2',    // Purple
            30000, '#9c27b0',    // Medium purple
            60000, '#ba68c8',    // Light purple
            100000, '#ce93d8',   // Very light purple
            350000, '#e1bee7'    // Pale purple - massive
        ],
        funding: [
            'interpolate',
            ['linear'],
            ['get', 'funding'],
            200, '#1a5490',      // Dark blue - low funding
            500, '#2874a6',
            1000, '#3498db',     // Medium blue
            2000, '#5dade2',
            3500, '#85c1e9',
            5500, '#aed6f1'      // Light blue - high funding
        ]
    };

    map.setPaintProperty('institutions', 'circle-color', colorExpressions[currentColorMetric]);
}

// Update statistics panel
function updateStatistics() {
    document.getElementById('total-institutions').textContent = globalStats.totalInstitutions;
    document.getElementById('avg-quality').textContent = globalStats.avgQuality;
    document.getElementById('avg-literacy').textContent = globalStats.avgLiteracy + '%';
    document.getElementById('total-enrollment').textContent =
        (globalStats.totalEnrollment / 1000000).toFixed(1) + 'M';
}

// Update legend based on current metrics
function updateLegend() {
    const sizeLabels = {
        enrollment: { unit: ' students', min: '1K', max: '350K' },
        quality: { unit: '/100', min: '50', max: '100' },
        literacy: { unit: '%', min: '40', max: '100' },
        funding: { unit: 'M USD', min: '200', max: '5500' }
    };

    const colorLabels = {
        quality: { min: 'Low Quality (50)', max: 'World Class (100)' },
        literacy: { min: 'Low Literacy (40%)', max: 'Universal (100%)' },
        enrollment: { min: 'Small (1K)', max: 'Massive (350K)' },
        funding: { min: 'Low Funded ($200M)', max: 'High Funded ($5.5B)' }
    };

    const sizeLabel = sizeLabels[currentSizeMetric];
    const colorLabel = colorLabels[currentColorMetric];

    document.getElementById('size-min-label').textContent = sizeLabel.min;
    document.getElementById('size-max-label').textContent = sizeLabel.max;
    document.getElementById('color-min-label').textContent = colorLabel.min;
    document.getElementById('color-max-label').textContent = colorLabel.max;
}

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

// Initialize legend
updateLegend();
