// @wuys/map · interactions/touch.js
//
// Touch interactions: single-finger pan (mirrors mouse drag), two-finger pinch
// zoom, double-tap fly-zoom. Pointer events on top of mouse handlers would
// double-fire on hybrid devices, so we go straight to TouchEvent.

import { NAV_ZOOM_MIN, NAV_ZOOM_MAX, NAV_LAT_MAX } from "../core/state.js";

export function attachTouch({ target, state, events, nav, renderer, animator }) {
  let mode = "idle";             // "idle" | "pan" | "pinch"
  let panStart = null;           // { x, y, lon, lat }
  let pinchStart = null;         // { dist, midX, midY, zoom, lon, lat }
  let lastTap = 0;
  let pixelMoved = 0;

  function touchMid(t1, t2) {
    return { x: (t1.clientX + t2.clientX) / 2, y: (t1.clientY + t2.clientY) / 2 };
  }
  function touchDist(t1, t2) {
    return Math.hypot(t1.clientX - t2.clientX, t1.clientY - t2.clientY);
  }

  target.addEventListener("touchstart", (e) => {
    if (e.target.closest && e.target.closest("[data-no-drag]")) return;
    animator.snap();
    if (e.touches.length === 1) {
      const t = e.touches[0];
      mode = "pan";
      pixelMoved = 0;
      panStart = { x: t.clientX, y: t.clientY, lon: state.nav.lon, lat: state.nav.lat };
      target.classList.add("wuys-map-dragging");
      state._isDragging = true;
    } else if (e.touches.length >= 2) {
      const [a, b] = [e.touches[0], e.touches[1]];
      mode = "pinch";
      const mid = touchMid(a, b);
      pinchStart = {
        dist: touchDist(a, b),
        midX: mid.x, midY: mid.y,
        zoom: state.nav.zoom,
        lon: state.nav.lon, lat: state.nav.lat,
      };
    }
  }, { passive: true });

  target.addEventListener("touchmove", (e) => {
    if (mode === "pan" && e.touches.length === 1) {
      e.preventDefault();
      const t = e.touches[0];
      const dx = t.clientX - panStart.x;
      const dy = t.clientY - panStart.y;
      pixelMoved = Math.max(pixelMoved, Math.hypot(dx, dy));
      if (state.view.mode === "flat") {
        const startScreen = renderer.worldToScreen({ lon: panStart.lon, lat: panStart.lat });
        const targetW = renderer.screenToWorld({ x: startScreen.x + dx, y: startScreen.y + dy });
        state.nav.lon = panStart.lon - (targetW.lon - panStart.lon);
        state.nav.lat = Math.max(-NAV_LAT_MAX, Math.min(NAV_LAT_MAX, panStart.lat - (targetW.lat - panStart.lat)));
      } else {
        const sensDeg = 0.28 / Math.max(0.5, state.nav.zoom);
        state.nav.lon = panStart.lon + dx * sensDeg;
        state.nav.lat = Math.max(-NAV_LAT_MAX, Math.min(NAV_LAT_MAX, panStart.lat + dy * sensDeg));
      }
      state.nav.tLon = state.nav.lon;
      state.nav.tLat = state.nav.lat;
      renderer.patch();
      events.emit("nav:change", state.nav);
    } else if (mode === "pinch" && e.touches.length >= 2) {
      e.preventDefault();
      const [a, b] = [e.touches[0], e.touches[1]];
      const dist = touchDist(a, b);
      const factor = dist / pinchStart.dist;
      const nextZoom = Math.max(NAV_ZOOM_MIN, Math.min(NAV_ZOOM_MAX, pinchStart.zoom * factor));
      state.nav.zoom = nextZoom;
      state.nav.tZoom = nextZoom;
      renderer.patch();
      events.emit("nav:change", state.nav);
    }
  }, { passive: false });

  target.addEventListener("touchend", (e) => {
    if (mode === "pan") {
      target.classList.remove("wuys-map-dragging");
      if (pixelMoved < 8) {
        // Tap: emit click-equivalent. Double-tap → zoom-in fly.
        const now = Date.now();
        if (now - lastTap < 280) {
          // Double-tap zoom
          state.nav.tZoom = Math.min(NAV_ZOOM_MAX, state.nav.tZoom * 1.8);
          animator.kick();
          lastTap = 0;
        } else {
          lastTap = now;
          // Emit click-like hit
          const tch = e.changedTouches && e.changedTouches[0];
          if (tch) {
            const hit = renderer.hitTest(tch.clientX, tch.clientY);
            if (hit) events.emit("country:click", hit.iso);
          }
        }
      }
    }
    if (e.touches.length === 0) {
      mode = "idle";
      panStart = null;
      pinchStart = null;
      state._isDragging = false;
      renderer.patch();
    } else if (e.touches.length === 1 && mode === "pinch") {
      // Pinch released into single-finger pan
      const t = e.touches[0];
      mode = "pan";
      pixelMoved = 0;
      panStart = { x: t.clientX, y: t.clientY, lon: state.nav.lon, lat: state.nav.lat };
    }
  }, { passive: true });

  target.addEventListener("touchcancel", () => {
    mode = "idle";
    panStart = null;
    pinchStart = null;
    target.classList.remove("wuys-map-dragging");
  }, { passive: true });
}
