/* ===================================================
   JAESWIFT.XYZ — 3D Globe (Globe.gl)
   eDEX-UI inspired rotating globe with server location
   =================================================== */

(function () {
    'use strict';

    const container = document.getElementById('globeViz');
    if (!container || typeof Globe === 'undefined') return;

    // Manchester coordinates
    const SERVER_LAT = 53.48;
    const SERVER_LNG = -2.24;

    // Wait for container to be visible and sized
    function initGlobe() {
        const rect = container.parentElement.getBoundingClientRect();
        const size = Math.min(rect.width, 340);

        if (size < 50) {
            setTimeout(initGlobe, 200);
            return;
        }

        const globe = Globe()
            .globeImageUrl('')
            .backgroundColor('rgba(0,0,0,0)')
            .width(size)
            .height(size)
            .showAtmosphere(true)
            .atmosphereColor('#00ff44')
            .atmosphereAltitude(0.2)
            // Hex polygons for land masses
            .hexPolygonsData([])
            // Points - server location
            .pointsData([{
                lat: SERVER_LAT,
                lng: SERVER_LNG,
                size: 0.6,
                color: '#00cc33',
                label: 'MANCHESTER'
            }])
            .pointAltitude('size')
            .pointColor('color')
            .pointRadius(0.4)
            .pointsMerge(false)
            // Rings - pulse effect
            .ringsData([{
                lat: SERVER_LAT,
                lng: SERVER_LNG,
                maxR: 3,
                propagationSpeed: 1.5,
                repeatPeriod: 1200
            }])
            .ringColor(function () { return '#00cc3380'; })
            .ringMaxRadius('maxR')
            .ringPropagationSpeed('propagationSpeed')
            .ringRepeatPeriod('repeatPeriod')
            // Labels
            .labelsData([{
                lat: SERVER_LAT,
                lng: SERVER_LNG,
                text: 'MCR // 53.48°N',
                color: '#00cc33',
                size: 0.7
            }])
            .labelColor('color')
            .labelSize('size')
            .labelDotRadius(0.3)
            .labelAltitude(0.01)
            .labelText('text')
            .labelResolution(2)
            // Custom globe material
            .onGlobeReady(function () {
                // Style the globe mesh
                var globeMesh = globe.scene().children.find(function (c) {
                    return c.type === 'Mesh' && c.geometry && c.geometry.type === 'SphereGeometry';
                });
                if (globeMesh && globeMesh.material) {
                    globeMesh.material.color.setHex(0x0a1a0a);
                    globeMesh.material.emissive.setHex(0x008800);
                    globeMesh.material.emissiveIntensity = 0.8;
                }
            })
            (container);

        // Auto rotate
        globe.controls().autoRotate = true;
        globe.controls().autoRotateSpeed = 0.4;
        globe.controls().enableZoom = false;
        globe.controls().enablePan = false;
        globe.controls().minPolarAngle = Math.PI * 0.35;
        globe.controls().maxPolarAngle = Math.PI * 0.65;

        // Point camera at Manchester
        globe.pointOfView({ lat: SERVER_LAT, lng: SERVER_LNG, altitude: 2.2 }, 1500);

        // Fetch country polygons for land outlines
        fetch('https://unpkg.com/world-atlas@2/countries-110m.json')
            .then(function (r) { return r.json(); })
            .then(function (worldData) {
                var countries = topojsonFeature(worldData, worldData.objects.countries).features;
                globe
                    .hexPolygonsData(countries)
                    .hexPolygonResolution(3)
                    .hexPolygonMargin(0.4)
                    .hexPolygonColor(function () {
                        return 'rgba(0, 220, 50, 0.55)';
                    })
                    .hexPolygonSideColor(function () {
                        return 'rgba(0, 255, 60, 0.6)';
                    })
                    .hexPolygonAltitude(0.005);
            })
            .catch(function () {
                // Fallback: no country data, globe still works
            });

        // ─── LIVE TRAFFIC ARCS — fetched from /api/visitor/recent-arcs ───
        var currentArcs = [];

        function parseNginxTs(ts) {
            // '20/Apr/2026:03:35:38 +0200' → Date
            if (!ts) return null;
            try {
                var parts = ts.match(/(\d+)\/(\w+)\/(\d+):(\d+):(\d+):(\d+)\s*([+-]\d{4})?/);
                if (!parts) return new Date(ts);
                var months = { Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11 };
                return new Date(Date.UTC(
                    parseInt(parts[3]),
                    months[parts[2]] || 0,
                    parseInt(parts[1]),
                    parseInt(parts[4]),
                    parseInt(parts[5]),
                    parseInt(parts[6])
                ));
            } catch (e) { return null; }
        }

        function timeAgo(ts) {
            var d = parseNginxTs(ts);
            if (!d) return '—';
            var s = Math.floor((Date.now() - d.getTime()) / 1000);
            if (s < 60) return s + 's ago';
            if (s < 3600) return Math.floor(s / 60) + 'm ago';
            if (s < 86400) return Math.floor(s / 3600) + 'h ago';
            return Math.floor(s / 86400) + 'd ago';
        }

        function buildArcsFromVisitors(visitors) {
            return (visitors || []).map(function (v) {
                // jitter lat/lon slightly so duplicates from same country don't overlap perfectly
                var jlat = (Math.random() - 0.5) * 1.2;
                var jlon = (Math.random() - 0.5) * 1.2;
                return {
                    startLat: v.lat + jlat,
                    startLng: v.lon + jlon,
                    endLat: SERVER_LAT,
                    endLng: SERVER_LNG,
                    color: ['rgba(0, 255, 60, 0.85)', 'rgba(20, 241, 149, 0.15)'],
                    country_code: v.country_code,
                    country_name: v.country_name,
                    page_viewed: v.page_viewed,
                    timestamp: v.timestamp,
                    label: (v.country_name || v.country_code || 'Unknown') + ' → MCR  ·  ' + timeAgo(v.timestamp) + '  ·  ' + (v.page_viewed || '/')
                };
            });
        }

        function fallbackArcs() {
            var cities = [
                { lat: 40.71, lng: -74.01, name: 'New York' },
                { lat: 35.68, lng: 139.69, name: 'Tokyo' },
                { lat: 48.86, lng: 2.35, name: 'Paris' },
                { lat: -33.87, lng: 151.21, name: 'Sydney' },
                { lat: 55.76, lng: 37.62, name: 'Moscow' },
                { lat: 1.35, lng: 103.82, name: 'Singapore' },
                { lat: 52.52, lng: 13.41, name: 'Berlin' },
                { lat: 34.05, lng: -118.24, name: 'LA' }
            ];
            return cities.map(function (c) {
                return {
                    startLat: c.lat, startLng: c.lng,
                    endLat: SERVER_LAT, endLng: SERVER_LNG,
                    color: ['rgba(0, 255, 60, 0.55)', 'rgba(0, 255, 60, 0.05)'],
                    label: c.name + ' → MCR (demo)'
                };
            });
        }

        function refreshArcs() {
            fetch('/api/visitor/recent-arcs', { cache: 'no-store' })
                .then(function (r) { return r.ok ? r.json() : []; })
                .then(function (visitors) {
                    if (!Array.isArray(visitors) || !visitors.length) {
                        currentArcs = fallbackArcs();
                    } else {
                        currentArcs = buildArcsFromVisitors(visitors.slice(0, 50));
                    }
                    globe.arcsData(currentArcs);
                    var countEl = document.getElementById('globeArcCount');
                    if (countEl) countEl.textContent = String(currentArcs.length);
                })
                .catch(function () {
                    if (!currentArcs.length) {
                        currentArcs = fallbackArcs();
                        globe.arcsData(currentArcs);
                    }
                });
        }

        globe
            .arcsData([])
            .arcColor('color')
            .arcDashLength(0.5)
            .arcDashGap(0.2)
            .arcDashInitialGap(function () { return Math.random(); })
            .arcDashAnimateTime(2200)
            .arcStroke(0.45)
            .arcAltitudeAutoScale(0.38)
            .arcLabel('label');

        refreshArcs();
        setInterval(refreshArcs, 30000);

        // Handle resize
        var resizeTimer;
        window.addEventListener('resize', function () {
            clearTimeout(resizeTimer);
            resizeTimer = setTimeout(function () {
                var newRect = container.parentElement.getBoundingClientRect();
                var newSize = Math.min(newRect.width, 340);
                globe.width(newSize).height(newSize);
            }, 250);
        });
    }

    // Topojson helper
    function topojsonFeature(topology, obj) {
        if (!obj || !obj.geometries) return { type: 'FeatureCollection', features: [] };
        return {
            type: 'FeatureCollection',
            features: obj.geometries.map(function (geom) {
                return {
                    type: 'Feature',
                    geometry: topojsonGeometry(topology, geom),
                    properties: geom.properties || {},
                    id: geom.id
                };
            })
        };
    }

    function topojsonGeometry(topology, obj) {
        var arcs = topology.arcs;
        var transform = topology.transform;

        function decodeArc(arcIdx) {
            var arc = arcs[arcIdx < 0 ? ~arcIdx : arcIdx];
            var coords = [];
            var x = 0, y = 0;
            for (var i = 0; i < arc.length; i++) {
                x += arc[i][0];
                y += arc[i][1];
                var lon = x, lat = y;
                if (transform) {
                    lon = lon * transform.scale[0] + transform.translate[0];
                    lat = lat * transform.scale[1] + transform.translate[1];
                }
                coords.push([lon, lat]);
            }
            if (arcIdx < 0) coords.reverse();
            return coords;
        }

        function decodeRing(arcIndices) {
            var coords = [];
            for (var i = 0; i < arcIndices.length; i++) {
                var arcCoords = decodeArc(arcIndices[i]);
                if (i > 0) arcCoords.shift();
                coords = coords.concat(arcCoords);
            }
            return coords;
        }

        var type = obj.type;
        if (type === 'Polygon') {
            return { type: 'Polygon', coordinates: obj.arcs.map(decodeRing) };
        } else if (type === 'MultiPolygon') {
            return {
                type: 'MultiPolygon',
                coordinates: obj.arcs.map(function (polygon) {
                    return polygon.map(decodeRing);
                })
            };
        } else if (type === 'GeometryCollection') {
            return {
                type: 'GeometryCollection',
                geometries: (obj.geometries || []).map(function (g) {
                    return topojsonGeometry(topology, g);
                })
            };
        }
        return { type: type, coordinates: [] };
    }

    // Init when DOM ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function () {
            setTimeout(initGlobe, 300);
        });
    } else {
        setTimeout(initGlobe, 300);
    }

})();
