// @wuys/map · layers/spotlights.js
//
// Renders a circle + halo + (on hover) a name label for each entity in
// `state.data.spotlights`. The circle scales inversely with zoom so a microstate
// stays visually findable at world view but doesn't dominate the country shape
// at high zoom — it shrinks toward zero around zoom 4+.

const SVG_NS = "http://www.w3.org/2000/svg";

export default function createSpotlightsLayer(opts = {}) {
  /** Map<iso, { g, halo, dot, label }> */
  const nodes = new Map();
  let group = null;
  let hoverIso = null;

  function build(ctx) {
    const { svg, state, events } = ctx;
    group = document.createElementNS(SVG_NS, "g");
    group.setAttribute("id", "layer-spotlights");
    group.setAttribute("class", "wuys-spotlights");
    svg.appendChild(group);

    for (const s of state.data.spotlights || []) {
      const g = document.createElementNS(SVG_NS, "g");
      g.setAttribute("data-iso", s.iso);
      g.setAttribute("data-name", s.name);
      g.setAttribute("display", "none");
      if (s.special) g.setAttribute("data-special", "1");

      const halo = document.createElementNS(SVG_NS, "circle");
      halo.setAttribute("class", "wuys-spotlight-halo");
      halo.setAttribute("r", "10");
      halo.setAttribute("fill", "transparent");
      halo.setAttribute("pointer-events", "none");
      g.appendChild(halo);

      const dot = document.createElementNS(SVG_NS, "circle");
      dot.setAttribute("class", "wuys-spotlight-dot");
      dot.setAttribute("r", "3");
      dot.setAttribute("cursor", "pointer");
      g.appendChild(dot);

      const label = document.createElementNS(SVG_NS, "text");
      label.setAttribute("class", "wuys-spotlight-label");
      label.setAttribute("text-anchor", "middle");
      label.setAttribute("font-size", "10");
      label.setAttribute("y", "-12");
      label.setAttribute("display", "none");
      label.setAttribute("pointer-events", "none");
      label.textContent = s.name;
      g.appendChild(label);

      group.appendChild(g);
      nodes.set(s.iso, { g, halo, dot, label, meta: s });

      // Event dispatch
      dot.addEventListener("mouseenter", () => {
        hoverIso = s.iso;
        label.removeAttribute("display");
        events.emit("spotlight:hover", s);
      });
      dot.addEventListener("mouseleave", () => {
        if (hoverIso === s.iso) hoverIso = null;
        label.setAttribute("display", "none");
        events.emit("spotlight:leave", s);
      });
      dot.addEventListener("click", (ev) => {
        ev.stopPropagation();
        events.emit("spotlight:click", s);
        events.emit("country:click", s.iso);
      });
    }

    applyTheme(ctx);
  }

  function patch(ctx) {
    const { state, theme, mode, screenForLabel } = ctx;
    const zoom = state.nav.zoom;
    // Hide spotlights at deep zoom — country shape itself is visible enough.
    const fadeStart = 3.0, fadeEnd = 5.5;
    let alpha = 1;
    if (zoom > fadeStart) alpha = Math.max(0, 1 - (zoom - fadeStart) / (fadeEnd - fadeStart));
    if (alpha <= 0.001) {
      group.setAttribute("display", "none");
      return;
    }
    group.removeAttribute("display");
    group.setAttribute("opacity", alpha.toFixed(3));

    const dotR = Math.max(1.4, 3.0 / Math.max(0.7, Math.pow(zoom, 0.55)));
    const haloR = dotR * 3.2;

    for (const [iso, node] of nodes) {
      const pos = screenForLabel(iso, node.meta);
      if (!pos) { node.g.setAttribute("display", "none"); continue; }
      node.g.removeAttribute("display");
      node.g.setAttribute("transform", "translate(" + pos.x.toFixed(2) + "," + pos.y.toFixed(2) + ")");
      node.halo.setAttribute("r", haloR.toFixed(2));
      node.dot.setAttribute("r", dotR.toFixed(2));
    }
  }

  function applyTheme(ctx) {
    if (!group) return;
    const sp = ctx.theme.spotlights;
    for (const [iso, node] of nodes) {
      const isSpecial = !!node.meta.special;
      node.dot.setAttribute("fill", isSpecial ? (sp.specialFill || sp.fill) : sp.fill);
      node.dot.setAttribute("stroke", isSpecial ? sp.specialBorder : sp.border);
      node.dot.setAttribute("stroke-width", "1");
      node.halo.setAttribute("stroke", sp.glow);
      node.halo.setAttribute("stroke-width", "1.5");
      node.halo.setAttribute("opacity", "0.6");
      node.label.setAttribute("fill", ctx.theme.labels.fill);
      node.label.setAttribute("stroke", ctx.theme.labels.stroke || "transparent");
      node.label.setAttribute("stroke-width", "0.6");
      node.label.setAttribute("paint-order", "stroke");
      node.label.setAttribute("font-family", ctx.theme.labels.fontFamily);
    }
  }

  function destroy() {
    if (group && group.parentNode) group.parentNode.removeChild(group);
    nodes.clear();
    group = null;
  }

  return { id: "spotlights", build, patch, applyTheme, destroy };
}
