type Coord = [number, number]; // [lon, lat]

function pointInRing(lon: number, lat: number, ring: Coord[]): boolean {
  // Ray-casting algorithm. Assumes ring is closed or open; works either way.
  let inside = false;
  const n = ring.length;
  if (n < 3) return false;

  for (let i = 0, j = n - 1; i < n; j = i++) {
    const xi = ring[i][0];
    const yi = ring[i][1];
    const xj = ring[j][0];
    const yj = ring[j][1];

    const intersect = yi > lat !== yj > lat && lon < ((xj - xi) * (lat - yi)) / (yj - yi + 0.0) + xi;
    if (intersect) inside = !inside;
  }

  return inside;
}

export function pointInPolygon(lon: number, lat: number, polygon: Coord[][]): boolean {
  // polygon: [outerRing, ...holes]
  if (!polygon.length) return false;
  if (!pointInRing(lon, lat, polygon[0])) return false;
  for (let i = 1; i < polygon.length; i++) {
    if (pointInRing(lon, lat, polygon[i])) return false;
  }
  return true;
}

export function pointInMultiPolygon(lon: number, lat: number, multiPolygon: Coord[][][]): boolean {
  for (const poly of multiPolygon) {
    if (pointInPolygon(lon, lat, poly)) return true;
  }
  return false;
}

