// Mapbox Globe Visualization 14: HPV Vaccine Impact on Cervical Cancer
// Demonstrates multi-layer correlation visualization with 3D extrusions,
// dual choropleth encoding, and gender health equity analysis

// 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: [20, 15],
    zoom: 1.6,
    pitch: 0
});

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

// Track current styling metrics
let currentSizeMetric = 'coverage';
let currentColorMetric = 'cancer-rate';
let show3DExtrusion = false;

// Expression definitions for different metrics
const sizeExpressions = {
    'coverage': [
        'interpolate',
        ['linear'],
        ['get', 'hpv_coverage_2024'],
        0, 4,          // No program
        20, 8,
        40, 12,
        60, 17,
        80, 23,
        95, 30         // Excellent coverage
    ],
    'cancer-rate': [
        'interpolate',
        ['linear'],
        ['get', 'cervical_cancer_incidence'],
        2, 4,          // Very low incidence
        5, 7,
        10, 11,
        15, 16,
        25, 22,
        35, 27,
        44, 32         // Very high incidence
    ],
    'lives-saved': [
        'interpolate',
        ['linear'],
        ['get', 'lives_saved_projected'],
        0, 4,
        100, 6,
        500, 9,
        1000, 12,
        5000, 18,
        10000, 24,
        86000, 35      // India (largest potential)
    ],
    'mortality': [
        'interpolate',
        ['linear'],
        ['get', 'cervical_cancer_mortality'],
        1.2, 4,
        3, 8,
        5, 12,
        10, 18,
        15, 24,
        30.4, 32       // Eswatini (highest)
    ]
};

const colorExpressions = {
    'coverage': [
        'interpolate',
        ['linear'],
        ['get', 'hpv_coverage_2024'],
        0, '#4a0e4e',      // Dark purple - no program
        15, '#6b1b6b',
        30, '#8e2a8e',
        50, '#b366ff',     // Medium purple
        70, '#d499ff',
        90, '#ebccff'      // Light purple - excellent coverage
    ],
    'cancer-rate': [
        'interpolate',
        ['linear'],
        ['get', 'cervical_cancer_incidence'],
        2, '#66ffb3',      // Green - very low incidence
        5, '#99ff99',
        10, '#ffff66',     // Yellow - moderate
        15, '#ffcc33',
        20, '#ff9933',     // Orange
        30, '#ff6633',
        40, '#ff3333',     // Red - high incidence
        44, '#cc0000'      // Dark red - very high
    ],
    'lives-saved': [
        'interpolate',
        ['linear'],
        ['get', 'lives_saved_projected'],
        0, '#0d4d4d',      // Dark teal
        500, '#1a7a7a',
        2000, '#26a69a',   // Teal
        5000, '#4db6ac',
        20000, '#80cbc4',
        86000, '#b2dfdb'   // Light teal - highest potential
    ],
    'mortality': [
        'interpolate',
        ['linear'],
        ['get', 'cervical_cancer_mortality'],
        1.2, '#66ffb3',    // Green - very low
        3, '#99ff99',
        6, '#ffff66',      // Yellow
        10, '#ffcc33',
        15, '#ff6633',     // Orange-red
        22, '#ff3333',
        30.4, '#cc0000'    // Dark red - very high
    ]
};

// 3D extrusion height expression (cancer burden)
const extrusionHeightExpression = [
    'interpolate',
    ['linear'],
    ['get', 'annual_deaths'],
    0, 0,
    100, 50000,
    500, 150000,
    1000, 250000,
    5000, 500000,
    10000, 800000,
    77000, 1500000     // India (highest deaths)
];

map.on('load', () => {
    // Configure globe atmosphere with purple-pink theme
    map.setFog({
        color: 'rgba(25, 15, 35, 0.9)',
        'high-color': 'rgba(80, 50, 120, 0.5)',
        'horizon-blend': 0.06,
        'space-color': 'rgba(8, 5, 15, 1)',
        'star-intensity': 0.8
    });

    // Add HPV vaccine data source
    map.addSource('hpv-data', {
        type: 'geojson',
        data: hpvVaccineData
    });

    // Main circle layer - vaccine coverage and cancer correlation
    map.addLayer({
        id: 'hpv-circles',
        type: 'circle',
        source: 'hpv-data',
        paint: {
            // SIZE: Based on current size metric
            'circle-radius': sizeExpressions[currentSizeMetric],

            // COLOR: Based on current color metric
            'circle-color': colorExpressions[currentColorMetric],

            // OPACITY: Zoom-responsive
            'circle-opacity': [
                'interpolate',
                ['linear'],
                ['zoom'],
                1, 0.8,
                3, 0.85,
                6, 0.92
            ],

            // STROKE: Highlight countries without programs
            'circle-stroke-color': [
                'case',
                ['==', ['get', 'hpv_coverage_2024'], 0],
                '#ff6eb4',     // Pink for no program
                '#ffffff'      // White for countries with programs
            ],

            'circle-stroke-width': [
                'case',
                ['==', ['get', 'hpv_coverage_2024'], 0],
                2.5,           // Thicker stroke for no program (attention)
                [
                    'interpolate',
                    ['linear'],
                    ['zoom'],
                    1, 0.5,
                    4, 1,
                    8, 1.5
                ]
            ]
        }
    });

    // 3D extrusion layer for cancer burden (initially hidden)
    map.addLayer({
        id: 'cancer-burden-3d',
        type: 'fill-extrusion',
        source: 'hpv-data',
        layout: {
            'visibility': 'none'
        },
        paint: {
            'fill-extrusion-color': [
                'interpolate',
                ['linear'],
                ['get', 'cervical_cancer_incidence'],
                2, '#4db6ac',      // Teal - low incidence
                10, '#ffeb3b',     // Yellow
                20, '#ff9800',     // Orange
                30, '#f44336',     // Red
                44, '#b71c1c'      // Dark red - high incidence
            ],
            'fill-extrusion-height': extrusionHeightExpression,
            'fill-extrusion-base': 0,
            'fill-extrusion-opacity': 0.85
        }
    });

    // Labels for high-burden countries
    map.addLayer({
        id: 'country-labels',
        type: 'symbol',
        source: 'hpv-data',
        filter: ['>=', ['get', 'annual_deaths'], 2000],
        layout: {
            'text-field': ['get', 'name'],
            'text-size': [
                'interpolate',
                ['linear'],
                ['get', 'annual_deaths'],
                2000, 10,
                10000, 12,
                77000, 14
            ],
            'text-offset': [0, 1.8],
            'text-anchor': 'top',
            'text-max-width': 8
        },
        paint: {
            'text-color': '#b366ff',
            'text-halo-color': '#0a0a0f',
            'text-halo-width': 2,
            'text-opacity': [
                'interpolate',
                ['linear'],
                ['zoom'],
                1, 0,
                2.5, 0.5,
                5, 0.85
            ]
        },
        minzoom: 2
    });

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

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

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

        // Determine coverage status
        let coverageStatus = 'low';
        if (props.hpv_coverage_2024 > 70) coverageStatus = 'high';
        else if (props.hpv_coverage_2024 > 40) coverageStatus = 'medium';

        // Determine cancer rate status (inverse)
        let cancerStatus = 'high';
        if (props.cervical_cancer_incidence < 10) cancerStatus = 'low';
        else if (props.cervical_cancer_incidence < 20) cancerStatus = 'medium';

        const programInfo = props.hpv_coverage_2024 > 0
            ? `Started: ${props.vaccine_program_started}<br/>
               Target Age: ${props.target_age}<br/>
               Policy: ${props.gender_policy === 'girls-and-boys' ? 'Girls & Boys' : 'Girls Only'}`
            : '<span style="color: #ff6eb4;">No vaccination program</span>';

        const html = `
            <div class="popup-title">${props.name}</div>

            <div class="popup-section">
                <div class="popup-label">HPV Vaccine Coverage (2024)</div>
                <div class="popup-value ${coverageStatus}">${props.hpv_coverage_2024}%</div>
            </div>

            <div class="popup-section">
                <div class="popup-label">Program Details</div>
                <div style="font-size: 11px; color: #d8c8e8; line-height: 1.5;">
                    ${programInfo}
                </div>
            </div>

            <div class="popup-section">
                <div class="popup-label">Cervical Cancer Incidence</div>
                <div class="popup-value ${cancerStatus}">${props.cervical_cancer_incidence} per 100,000</div>
            </div>

            <div class="popup-section">
                <div class="popup-label">Annual Deaths</div>
                <div class="popup-value">${props.annual_deaths.toLocaleString()}</div>
            </div>

            <div class="popup-section">
                <div class="popup-label">Potential Lives Saved (Full Coverage)</div>
                <div class="popup-value high">${props.lives_saved_projected.toLocaleString()}</div>
            </div>

            <div class="popup-section">
                <div class="popup-label">Income Level</div>
                <div style="font-size: 11px; color: #b8a4cc; text-transform: capitalize;">
                    ${props.income_level.replace('-', ' ')}
                </div>
            </div>
        `;

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

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

    // Auto-rotation logic
    function spinGlobe() {
        if (!userInteracting && rotationActive) {
            const center = map.getCenter();
            center.lng -= 0.15;
            map.easeTo({ center, duration: 100, easing: (n) => n });
        }
    }

    const spinInterval = setInterval(spinGlobe, 100);

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

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

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

    // Control: Toggle 3D comparison mode
    document.getElementById('toggle-comparison').addEventListener('click', (e) => {
        show3DExtrusion = !show3DExtrusion;

        if (show3DExtrusion) {
            // Show 3D extrusions, increase pitch for better view
            map.setLayoutProperty('cancer-burden-3d', 'visibility', 'visible');
            map.easeTo({ pitch: 45, duration: 1000 });
            e.target.textContent = 'Hide 3D Cancer Burden';
            e.target.classList.add('active');
        } else {
            // Hide 3D extrusions, reset pitch
            map.setLayoutProperty('cancer-burden-3d', 'visibility', 'none');
            map.easeTo({ pitch: 0, duration: 1000 });
            e.target.textContent = 'Toggle 3D Cancer Burden';
            e.target.classList.remove('active');
        }
    });

    // Control: Size metric selector
    document.getElementById('size-metric').addEventListener('change', (e) => {
        currentSizeMetric = e.target.value;
        updateCircleSize();
        updateLegend();
    });

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

    // Update circle size based on metric
    function updateCircleSize() {
        map.setPaintProperty('hpv-circles', 'circle-radius', sizeExpressions[currentSizeMetric]);
    }

    // Update circle color based on metric
    function updateCircleColor() {
        map.setPaintProperty('hpv-circles', 'circle-color', colorExpressions[currentColorMetric]);
    }

    // Update legend to match current metrics
    function updateLegend() {
        const metricLabels = {
            'coverage': {
                name: 'HPV Vaccine Coverage',
                min: '0% (No program)',
                max: '95% (High coverage)',
                gradient: 'coverage-gradient'
            },
            'cancer-rate': {
                name: 'Cervical Cancer Incidence',
                min: 'Low (2 per 100K)',
                max: 'High (44 per 100K)',
                gradient: 'cancer-gradient'
            },
            'lives-saved': {
                name: 'Lives That Could Be Saved',
                min: '0',
                max: '86,000 (India)',
                gradient: 'lives-saved-gradient'
            },
            'mortality': {
                name: 'Cervical Cancer Mortality',
                min: 'Low (1.2 per 100K)',
                max: 'High (30.4 per 100K)',
                gradient: 'cancer-gradient'
            }
        };

        const colorInfo = metricLabels[currentColorMetric];
        const sizeInfo = metricLabels[currentSizeMetric];

        // Update color legend
        document.getElementById('color-metric-label').textContent = colorInfo.name;
        document.getElementById('color-min-label').textContent = colorInfo.min;
        document.getElementById('color-max-label').textContent = colorInfo.max;

        const colorGradient = document.getElementById('color-gradient');
        colorGradient.className = 'legend-gradient ' + colorInfo.gradient;

        // Update size legend
        document.getElementById('size-metric-label').textContent = sizeInfo.name;
        document.getElementById('size-min-label').textContent = sizeInfo.min;
        document.getElementById('size-max-label').textContent = sizeInfo.max;
    }

    // Initialize legend
    updateLegend();
});
