// Xbox/PlayStation/generieke gamepad-ondersteuning. Mapt knoppen en sticks
// op synthetische keyboard-events op window, zodat alle bestaande spel-
// keyhandlers werken zonder aanpassingen.
//
//   D-pad of linker stick → pijltjes
//   A (Xbox) / ✕ (PS), knop 0 → spatie, primary action (springen, hard drop)
//   B (Xbox) / ◯ (PS), knop 1 → Escape, sluiten
//   Y (Xbox) / △ (PS), knop 3 → ArrowUp, alternatieve rotate/jump
//   Start, knop 9             → Enter, starten/bevestigen
//
// Auto-repeat alleen op horizontaal + neerwaarts pijltje zodat Tetris en
// vergelijkbare spellen vasthouden netjes verwerken.
(function installGamepadBridge() {
  if (typeof window === "undefined") return;
  if (!navigator.getGamepads) return;
  if (window.__hpGamepadBridgeInstalled) return;
  window.__hpGamepadBridgeInstalled = true;

  const BTN_MAP = {
    0:  " ",
    1:  "Escape",
    3:  "ArrowUp",
    9:  "Enter",
    12: "ArrowUp",
    13: "ArrowDown",
    14: "ArrowLeft",
    15: "ArrowRight",
  };
  const AXIS_THRESHOLD = 0.55;
  const REPEAT_KEYS = new Set(["ArrowLeft", "ArrowRight", "ArrowDown"]);
  const REPEAT_DELAY_MS = 220;
  const REPEAT_INTERVAL_MS = 80;

  const prevBtn = {};
  const prevAxis = [{}, {}];
  const repeatDelayTimers = {};
  const repeatIntervalTimers = {};

  function keyToCode(key) {
    if (key === " ") return "Space";
    if (key.startsWith("Arrow")) return key;
    return key;
  }
  function dispatchKey(type, key) {
    window.dispatchEvent(new KeyboardEvent(type, {
      key, code: keyToCode(key), bubbles: true, cancelable: true,
    }));
  }
  function press(key) {
    dispatchKey("keydown", key);
    if (REPEAT_KEYS.has(key) && !repeatDelayTimers[key] && !repeatIntervalTimers[key]) {
      repeatDelayTimers[key] = setTimeout(() => {
        repeatDelayTimers[key] = null;
        repeatIntervalTimers[key] = setInterval(() => dispatchKey("keydown", key), REPEAT_INTERVAL_MS);
      }, REPEAT_DELAY_MS);
    }
  }
  function release(key) {
    if (repeatDelayTimers[key]) { clearTimeout(repeatDelayTimers[key]); repeatDelayTimers[key] = null; }
    if (repeatIntervalTimers[key]) { clearInterval(repeatIntervalTimers[key]); repeatIntervalTimers[key] = null; }
    dispatchKey("keyup", key);
  }

  let raf = 0;
  function poll() {
    const pads = navigator.getGamepads ? navigator.getGamepads() : [];
    let active = null;
    for (const gp of pads) { if (gp) { active = gp; break; } }
    if (active) {
      for (const idxStr of Object.keys(BTN_MAP)) {
        const i = +idxStr;
        const key = BTN_MAP[idxStr];
        const b = active.buttons[i];
        const pressed = !!(b && b.pressed);
        if (pressed && !prevBtn[i]) press(key);
        else if (!pressed && prevBtn[i]) release(key);
        prevBtn[i] = pressed;
      }
      const axisMap = [
        { neg: "ArrowLeft", pos: "ArrowRight" },
        { neg: "ArrowUp",   pos: "ArrowDown"  },
      ];
      for (let ai = 0; ai < axisMap.length; ai++) {
        const v = active.axes[ai] || 0;
        const negNow = v < -AXIS_THRESHOLD;
        const posNow = v >  AXIS_THRESHOLD;
        if (negNow !== !!prevAxis[ai].neg) {
          if (negNow) press(axisMap[ai].neg); else release(axisMap[ai].neg);
          prevAxis[ai].neg = negNow;
        }
        if (posNow !== !!prevAxis[ai].pos) {
          if (posNow) press(axisMap[ai].pos); else release(axisMap[ai].pos);
          prevAxis[ai].pos = posNow;
        }
      }
    }
    raf = requestAnimationFrame(poll);
  }

  function start() { if (!raf) raf = requestAnimationFrame(poll); }

  // Korte toast bovenaan het scherm zodra een controller (dis)connect.
  // Gebruikt vanilla DOM omdat de bridge buiten React draait. Stijl matcht
  // de comic-look van de site (Bangers, harde slagschaduw, knal-rood/geel).
  let toastEl = null;
  let toastTimer = 0;
  function showToast(msg, color) {
    if (!document.body) return;
    if (!toastEl) {
      toastEl = document.createElement("div");
      toastEl.setAttribute("role", "status");
      toastEl.setAttribute("aria-live", "polite");
      toastEl.style.cssText = [
        "position:fixed", "top:18px", "left:50%",
        "transform:translateX(-50%) translateY(-14px)",
        "z-index:9999",
        "padding:10px 18px",
        "border:3px solid #1A1A1A",
        "box-shadow:4px 4px 0 #1A1A1A",
        "font-family:'Bangers', sans-serif",
        "font-size:20px",
        "letter-spacing:0.04em",
        "color:#1A1A1A",
        "pointer-events:none",
        "opacity:0",
        "max-width:min(90vw, 460px)",
        "white-space:nowrap",
        "overflow:hidden",
        "text-overflow:ellipsis",
        "transition:opacity 220ms ease, transform 220ms ease",
      ].join(";");
      document.body.appendChild(toastEl);
    }
    toastEl.textContent = msg;
    toastEl.style.background = color;
    requestAnimationFrame(() => {
      toastEl.style.opacity = "1";
      toastEl.style.transform = "translateX(-50%) translateY(0)";
    });
    if (toastTimer) clearTimeout(toastTimer);
    toastTimer = setTimeout(() => {
      if (!toastEl) return;
      toastEl.style.opacity = "0";
      toastEl.style.transform = "translateX(-50%) translateY(-14px)";
    }, 3200);
  }

  window.addEventListener("gamepadconnected", () => {
    start();
    showToast("🎮 Controller verbonden", "#FFD23F");
  });
  window.addEventListener("gamepaddisconnected", () => {
    showToast("🎮 Controller losgekoppeld", "#FF8C1A");
  });
  start();

  // Test-hook, alleen aangeroepen door de geautomatiseerde verificatie. Doet
  // 1 polling-stap zodat tests niet hoeven te wachten op requestAnimationFrame
  // (die in een verborgen tab gethrottled wordt naar 0Hz).
  if (typeof window !== "undefined") window.__hpGamepadPumpOnce = poll;
})();
