// @wuys/map · layers/contested.js
//
// Hand-traced contested/occupied regions, projected per frame. They render on
// top of the country layer so they're visible at every zoom.

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

export default function createContestedLayer(opts = {}) {
  /** Map<iso, { path, meta }> */
  const nodes = new Map();
  let group = null;

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

    for (const r of state.data.contestedRegions || []) {
      const p = document.createElementNS(SVG_NS, "path");
      p.setAttribute("data-iso", r.iso);
      p.setAttribute("data-name", r.name);
      p.setAttribute("data-contested", "1");
      p.setAttribute("d", "M0,0");
      p.setAttribute("display", "none");
      group.appendChild(p);
      nodes.set(r.iso, { path: p, meta: r });

      p.addEventListener("mouseenter", () => events.emit("contested:hover", r));
      p.addEventListener("mouseleave", () => events.emit("contested:leave", r));
      p.addEventListener("click", () => events.emit("contested:click", r));
    }

    applyTheme(ctx);
  }

  function patch(ctx) {
    const { state, theme, mode } = ctx;
    const helpers = ctx;
    for (const [iso, node] of nodes) {
      const d = projectRing(node.meta.points, helpers);
      if (!d) { node.path.setAttribute("display", "none"); continue; }
      node.path.removeAttribute("display");
      node.path.setAttribute("d", d);
    }
  }

  function projectRing(points, ctx) {
    // Defer to renderer-supplied helpers if available, otherwise use a simple
    // EE-only fallback. The renderer-provided projector is normally used.
    if (ctx.projectRing) return ctx.projectRing(points);
    // SVG renderer hands us EE / horizon clippers via the context; we need our
    // own copy of the projection for layers added late. For now we trust the
    // renderer to expose a private path-builder via `ctx._projectRing`.
    if (ctx._projectRing) return ctx._projectRing(points);
    return "";
  }

  function applyTheme(ctx) {
    if (!group) return;
    const c = ctx.theme.contested;
    for (const [iso, node] of nodes) {
      node.path.setAttribute("fill", c.fill);
      node.path.setAttribute("stroke", c.stroke);
      node.path.setAttribute("stroke-width", c.strokeWidth);
      if (c.strokeDasharray) node.path.setAttribute("stroke-dasharray", c.strokeDasharray);
      else node.path.removeAttribute("stroke-dasharray");
      node.path.setAttribute("vector-effect", "non-scaling-stroke");
      node.path.setAttribute("pointer-events", "all");
      node.path.setAttribute("cursor", "pointer");
    }
  }

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

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