// Radius focus (Wave 3.1) — all traffic within 250 nm of where you're looking,
// via adsb.lol's free lat/lon/dist query (proxy/adsb/lat/.../lon/.../dist/250).
// Camera-driven: refetches when you stop panning/zooming, plus a slow refresh
// for freshness. Most useful zoomed into a region. Live-only; off by default.

export default function create(ctx) {
  const { viewer, Cesium, lib, ui } = ctx;
  const bc = viewer.scene.primitives.add(new Cesium.BillboardCollection());
  const glyph = lib.aircraftGlyph();
  const DIST_NM = 250; // adsb.lol free radius cap

  let enabled = false;
  let isLive = true;
  let inFlight = false;
  let debounce = null;
  let poller = null;
  let lastKey = null;

  bc.show = false;
  ui.addLayer('radius', `Traffic near view (${DIST_NM}nm)`, false, (on) => {
    enabled = on;
    bc.show = on && isLive;
    if (on && isLive) { refresh(); ensurePoller(); }
    else { clearInterval(poller); poller = null; ui.setStatus('radius', on ? 'locating…' : '', on ? 'warn' : 'ok'); }
  });

  viewer.camera.percentageChanged = 0.25; // fire camera.changed a bit more eagerly
  viewer.camera.changed.addEventListener(() => {
    if (!enabled || !isLive) return;
    if (debounce) clearTimeout(debounce);
    debounce = setTimeout(refresh, 1800); // refetch after panning stops
  });

  function ensurePoller() {
    if (poller) return;
    poller = setInterval(() => { if (enabled && isLive && !document.hidden) refresh(); }, 60000);
  }

  // Center = camera nadir point, rounded (also improves proxy cache hits).
  function center() {
    const c = viewer.camera.positionCartographic;
    return [
      +Cesium.Math.toDegrees(c.latitude).toFixed(2),
      +Cesium.Math.toDegrees(c.longitude).toFixed(2),
    ];
  }

  async function refresh() {
    if (!enabled || !isLive || document.hidden || inFlight) return;
    const [lat, lon] = center();
    if (!isFinite(lat) || !isFinite(lon)) return;
    const key = `${lat}/${lon}`;
    lastKey = key;
    inFlight = true;
    try {
      const res = await fetch(`proxy/adsb/lat/${lat}/lon/${lon}/dist/${DIST_NM}`);
      if (key !== lastKey) return; // camera moved again mid-fetch — stale
      if (!res.ok) { ui.setStatus('radius', `HTTP ${res.status}`, 'warn'); return; }
      const data = await res.json();
      const list = Array.isArray(data.ac) ? data.ac : [];
      bc.removeAll();
      let n = 0;
      for (const a of list) {
        if (a.lat == null || a.lon == null) continue;
        const altFt = typeof a.alt_baro === 'number' ? a.alt_baro : 0;
        bc.add({
          position: Cesium.Cartesian3.fromDegrees(a.lon, a.lat, altFt * 0.3048),
          image: glyph,
          color: lib.cz('#7bff9d'),
          rotation: lib.headingToRotation(a.track),
          scale: 0.7,
          disableDepthTestDistance: 50000, // occlude when behind the globe (far side)
          id: { layer: 'radius', hex: a.hex, flight: (a.flight || '').trim(), t: a.t,
                reg: a.r, altFt, gs: a.gs, track: a.track },
        });
        n++;
      }
      ui.setStatus('radius', `${n} within ${DIST_NM}nm of view`, 'ok');
    } catch {
      ui.setStatus('radius', 'network error', 'warn');
    } finally {
      inFlight = false;
    }
  }

  function onClockTick(currentTime, live) {
    isLive = live;
    if (!isLive) { bc.show = false; return; }
    bc.show = enabled;
    if (enabled) { refresh(); ensurePoller(); }
  }

  function handlePick(picked) {
    if (picked?.id?.layer !== 'radius') return false;
    const id = picked.id;
    ui.showPickOverlay('✈ ' + (id.flight || id.hex || '—'), [
      ['Type', id.t || '—'], ['Reg', id.reg || '—'],
      ['Altitude', `${Math.round(id.altFt || 0)} ft`], ['Speed', `${Math.round(id.gs || 0)} kt`],
    ]);
    return true;
  }
  function clearPick() { ui.hidePickOverlay(); }

  document.addEventListener('visibilitychange', () => { if (!document.hidden && enabled && isLive) refresh(); });

  return { id: 'radius', onClockTick, handlePick, clearPick };
}
