import type { MapProjection } from "../geometry/mapProjection";
import type { MapPolygon } from "../model/mapTypes";

type Pt = { x: number; y: number };

function unwrapX(points: Pt[], worldSize: number): Pt[] {
  if (points.length === 0) return [];
  const out: Pt[] = [points[0]];
  let prevX = points[0].x;
  for (let i = 1; i < points.length; i++) {
    let x = points[i].x;
    while (x - prevX > worldSize / 2) x -= worldSize;
    while (prevX - x > worldSize / 2) x += worldSize;
    out.push({ x, y: points[i].y });
    prevX = x;
  }
  return out;
}

function inView(points: Pt[], dx: number, vw: number, vh: number): boolean {
  return points.some((p) => {
    const x = p.x + dx;
    return x >= -64 && x <= vw + 64 && p.y >= -64 && p.y <= vh + 64;
  });
}

function tracePath(ctx: CanvasRenderingContext2D, points: Pt[], dx: number) {
  ctx.beginPath();
  for (let i = 0; i < points.length; i++) {
    if (i === 0) ctx.moveTo(points[i].x + dx, points[i].y);
    else ctx.lineTo(points[i].x + dx, points[i].y);
  }
  ctx.closePath();
}

export function drawSwath(
  ctx: CanvasRenderingContext2D,
  polygons: MapPolygon[],
  projection: MapProjection,
  viewport: { width: number; height: number }
) {
  ctx.save();
  ctx.fillStyle = "rgba(104, 195, 189, 0.10)";
  ctx.strokeStyle = "rgba(104, 195, 189, 0.40)";
  ctx.lineWidth = 1;
  for (const polygon of polygons) {
    if (polygon.points.length < 3) continue;
    const raw = polygon.points.map((p) => projection.project(p));
    const pts = unwrapX(raw, projection.worldSize);
    for (const dx of [0, projection.worldSize, -projection.worldSize]) {
      if (!inView(pts, dx, viewport.width, viewport.height)) continue;
      tracePath(ctx, pts, dx);
      ctx.fill();
      ctx.stroke();
    }
  }
  ctx.restore();
}
