// @wuys/map · data/loader.js
//
// Lazy data loaders for the topology + flag dictionaries. Both files are
// SHIPPED AS WINDOW-GLOBAL JS BUNDLES (not raw JSON) so they work over
// `file://` without fetch / CORS. We:
//
//   1. If `window[GLOBAL]` is already set, resolve immediately (cached).
//   2. Otherwise, inject a `<script src="…">` tag and wait for `onload`.
//
// In-flight requests are deduplicated so concurrent callers share one fetch.

let _topoPromise = null;
let _flagsPromise = null;
let _flagPositionsPromise = null;

/**
 * Inject a script tag and resolve when `window[globalName]` is populated.
 * Deduplicates by checking the global before injecting.
 */
function loadScriptGlobal(scriptSrc, globalName) {
  if (typeof window !== "undefined" && window[globalName] != null) {
    return Promise.resolve(window[globalName]);
  }
  return new Promise((resolve, reject) => {
    const s = document.createElement("script");
    s.src = scriptSrc;
    s.async = true;
    s.onload = () => {
      if (window[globalName] == null) {
        reject(new Error("Script loaded but " + globalName + " not set: " + scriptSrc));
      } else {
        resolve(window[globalName]);
      }
    };
    s.onerror = () => reject(new Error("Failed to load " + scriptSrc));
    document.head.appendChild(s);
  });
}

/**
 * Load topology bundle. Returns `{ topo, numToIso }`.
 * @param {{ url?: string, onProgress?: () => void }} opts
 */
export function loadTopology(opts = {}) {
  if (_topoPromise) return _topoPromise;
  const src = opts.url || "world-topo-data.js?v=4";
  _topoPromise = loadScriptGlobal(src, "WUYS_WORLD_TOPO");
  return _topoPromise;
}

/**
 * Load flags bundle. Returns the iso → dataURI dictionary.
 */
export function loadFlags(opts = {}) {
  if (_flagsPromise) return _flagsPromise;
  const src = opts.url || "flags-data.js?v=8";
  _flagsPromise = loadScriptGlobal(src, "WUYS_FLAGS").then((data) => {
    if (data && data.flags) return data.flags;
    return data;
  });
  return _flagsPromise;
}

/**
 * Load hand-curated flag positions (Natural Earth label points). Returns the
 * iso → [{ lon, lat, rank, name }] dictionary, or {} if the file isn't shipped.
 * Optional: the map degrades gracefully to polylabel anchors when missing.
 */
export function loadFlagPositions(opts = {}) {
  if (_flagPositionsPromise) return _flagPositionsPromise;
  const src = opts.url || "flag-positions.js?v=1";
  _flagPositionsPromise = loadScriptGlobal(src, "WUYS_FLAG_POSITIONS").catch(() => ({}));
  return _flagPositionsPromise;
}
