/* ============================================================
   MANEUVER TOOL — virtual articulated movement ruler
   Speed = number of segments. Each joint bends the path
   left/straight/right (notches −2..+2). Shows projected path
   + ghost of the resulting position; confirm applies the move.
   (Not a rules engine — purely a placement aid.)
   ============================================================ */

const MV_STEP = 22.5;   // degrees per yaw notch
const MV_SEG  = 118;    // world units per speed segment
const MV_MAX  = 2;      // max notch per joint

function computeManeuver(ship, yaw, speedDelta = 0) {
  const speed = Math.max(0, (ship.speed | 0) + (speedDelta | 0));
  let h = ship.facing, x = ship.x, y = ship.y;
  const pts = [{ x, y }], heads = [h];
  for (let k = 0; k < speed; k++) {
    h += (yaw[k] || 0) * MV_STEP;
    const r = h * Math.PI / 180;
    x += Math.sin(r) * MV_SEG;
    y += -Math.cos(r) * MV_SEG;
    pts.push({ x, y }); heads.push(h);
  }
  return { pts, heads, speed, end: { x, y, facing: ((h % 360) + 360) % 360 } };
}

const MV_BOX = 2600, MV_C = MV_BOX / 2;

function ManeuverLayer({ ship, yaw, z, nav, speedDelta = 0, showArcs = true, onSpeedDelta, onYaw, onConfirm, onCancel }) {
  const fc = FACTIONS[ship.faction].color;
  const m = computeManeuver(ship, yaw, speedDelta);
  // Navigate: precies één joint mag één klik verder (±3)
  // Nav Team / Engine Techs: extra yaw-klik(ken) per gewricht, bovenop de Navigate-dial-bonus
  const extraYaw = upgradeExtraYaw(ship);
  const yawLim = (k) => (nav && !yaw.some((v, i) => i !== k && Math.abs(v || 0) > MV_MAX) ? MV_MAX + 1 : MV_MAX) + extraYaw;
  const px = BASE_SIZES[ship.baseSize].px;
  const rel = (p) => [p.x - ship.x + MV_C, p.y - ship.y + MV_C];
  const stop = (e) => e.stopPropagation();

  const spine = m.pts.map(rel).map(([x, y], i) => `${i ? "L" : "M"} ${x} ${y}`).join(" ");
  const HULL = HULL_PATHS[ship.baseSize] || HULL_PATHS.medium;
  const NOSE = NOSE_PATHS[ship.baseSize] || NOSE_PATHS.medium;
  const [ex, ey] = rel(m.end);

  // perpendicular tick at each segment boundary
  const ticks = [];
  for (let k = 1; k <= m.speed; k++) {
    const [x, y] = rel(m.pts[k]);
    const h = m.heads[k] * Math.PI / 180;
    const px2 = Math.cos(h), py2 = Math.sin(h); // along-heading
    const tx = -py2, ty = px2; // perpendicular
    const L = px * 0.42;
    ticks.push(<line key={k} className="mv-tick" x1={x - tx * L} y1={y - ty * L} x2={x + tx * L} y2={y + ty * L} />);
  }

  return (
    <>
      {/* world-space path + ghost (scales with board) */}
      <svg className="mv-layer" width={MV_BOX} height={MV_BOX} viewBox={`0 0 ${MV_BOX} ${MV_BOX}`}
           style={{ left: ship.x, top: ship.y, marginLeft: -MV_C, marginTop: -MV_C, "--fc": fc }}>
        {m.speed > 0 ? <>
          <path className="mv-spine-bg" d={spine} />
          <path className="mv-spine" d={spine} />
          {ticks}
          {/* range-ringen op de landingsplek: zie wat je na de zet kunt raken */}
          {showArcs ? (
            <g className="mv-rng" transform={`translate(${ex} ${ey})`}>
              <circle className="mv-rng-ring" r={RANGE_DIST.long} />
              <circle className="mv-rng-ring" r={RANGE_DIST.medium} />
              <circle className="mv-rng-ring" r={RANGE_DIST.close} />
              {[45, 135, 225, 315].map((a) => {
                const b = (a + m.end.facing) * Math.PI / 180;
                return <line key={a} className="mv-rng-arcline" x1={0} y1={0} x2={Math.sin(b) * RANGE_DIST.long} y2={-Math.cos(b) * RANGE_DIST.long} />;
              })}
            </g>
          ) : null}
          <g transform={`translate(${ex} ${ey}) rotate(${m.end.facing}) scale(${px / 100}) translate(-50 -50)`}>
            <path className="mv-ghost-fill" d={HULL} />
            <path className="mv-ghost-nose" d={NOSE} />
            <path className="mv-ghost-stroke" d={HULL} />
          </g>
        </> : null}
      </svg>

      {/* screen-constant controls (counter-scaled) */}
      {m.speed === 0 ? (
        <div className="mv-joint mv-note" style={{ left: ship.x, top: ship.y - px * 0.8, transform: `translate(-50%,-50%) scale(${1 / z})` }}
             onPointerDown={stop}>
          <span className="mv-note-txt">Speed 0 — {nav ? "Navigate: +1 snelheid?" : "zet snelheid hoger"}</span>
          {nav && onSpeedDelta ? <button className="mv-confirm" onClick={() => onSpeedDelta(1)} disabled={speedDelta >= 1}>SPD +1</button> : null}
          <button className="mv-cancel" onClick={onCancel}>✕</button>
        </div>
      ) : null}

      {m.speed > 0 && m.pts.slice(0, m.speed).map((p, k) => {
        const [x, y] = [p.x, p.y];
        return (
          <div className="mv-joint" key={k} style={{ left: x, top: y, transform: `translate(-50%,-50%) scale(${1 / z})`, "--fc": fc }}
               onPointerDown={stop}>
            <button onClick={() => onYaw(k, -1)} disabled={(yaw[k] || 0) <= -yawLim(k)} aria-label="links">◄</button>
            <span className="mv-notch">{(yaw[k] || 0) === 0 ? "•" : (yaw[k] > 0 ? "+" + yaw[k] : yaw[k])}</span>
            <button onClick={() => onYaw(k, 1)} disabled={(yaw[k] || 0) >= yawLim(k)} aria-label="rechts">►</button>
          </div>
        );
      })}

      {m.speed > 0 ? (
        <div className="mv-end-ctrls" style={{ left: ex - MV_C + ship.x, top: ey - MV_C + ship.y, transform: `translate(-50%,-160%) scale(${1 / z})`, "--fc": fc }}
             onPointerDown={stop}>
          {nav && onSpeedDelta ? (
            <>
              <button className="mv-cancel" onClick={() => onSpeedDelta(-1)} disabled={speedDelta <= -1} title="Navigate: −1 snelheid">−</button>
              <span className="mv-notch" title="Snelheid deze manoeuvre">SPD {m.speed}</span>
              <button className="mv-cancel" onClick={() => onSpeedDelta(1)} disabled={speedDelta >= 1} title="Navigate: +1 snelheid">+</button>
            </>
          ) : null}
          <button className="mv-confirm" onClick={onConfirm}>✓ Verplaats</button>
          <button className="mv-cancel" onClick={onCancel}>✕</button>
        </div>
      ) : null}
    </>
  );
}

Object.assign(window, { ManeuverLayer, computeManeuver, MV_MAX });
