/**
 * Centralised map config: initial view + pan/zoom limits.
 *
 * All numeric framing knobs live here so they're easy to find and tune.
 */

/**
 * Default view used on first load and by the Reset View button.
 *
 * Framing target: Mediterranean coast visible on the left, the PI region
 * (Dead Sea / Sea of Galilee) centered, with ~50km of buffer + Sinai
 * showing at the bottom-left.
 */
export const INITIAL_VIEW = {
  longitude: 34.8,
  latitude: 31.9,
  zoom: 6.7,
} as const;

export type InitialView = typeof INITIAL_VIEW;

/**
 * P6 -- the canonical view, expressed as a BOUNDING BOX rather than a
 * centre + zoom.
 *
 * Bill asked for two specific edges at once: a northern crop just above PI's
 * northern tip, and a southern crop pulled far enough down that the corner of
 * Saudi Arabia stays visible at bottom-right ("to make the point of how close
 * Saudi is"). A fixed centre + zoom cannot honour both edges, because how much
 * latitude fits on screen depends on the browser window's size and aspect
 * ratio -- the same numbers frame differently on his monitor and on a laptop.
 *
 * `fitBounds` against this box pins the north and south edges on every screen
 * instead, which is what he actually asked for. On the usual landscape window
 * latitude is the constraining dimension, so the extra width simply shows more
 * of Egypt and Jordan either side.
 *
 * South edge sits below the Saudi/Jordan coastal border (~29.35 N) so the
 * Saudi corner is inside the frame, not on its edge.
 *
 * Format: [[west, south], [east, north]]
 */
export const CANONICAL_BOUNDS: [[number, number], [number, number]] = [
  [33.8, 29.15], // SW -- south of the Saudi/Jordan Gulf-of-Aqaba border
  [35.9, 33.45], // NE -- just above PI's northern tip
];

/** Padding, in screen px, left around {@link CANONICAL_BOUNDS} when fitting. */
export const CANONICAL_FIT_PADDING = 24;

/**
 * Bounding box of the PI landmass itself, used by the P5 pan-tether to decide
 * whether PI has left the screen. Deliberately the region, not the drawing
 * boundary -- a few km either way makes no difference to "can the user still
 * see the country they are meant to be dividing".
 */
export const PI_BBOX: { west: number; south: number; east: number; north: number } = {
  west: 34.2,
  south: 29.45,
  east: 35.9,
  north: 33.35,
};

/**
 * Mapbox pan bounds: a rectangle the camera centre cannot leave.
 *
 * P5 widened this considerably. Bill asked to be able to pan out far enough to
 * see Cyprus, Türkiye, Saudi Arabia and Egypt in frame -- the surrounding
 * region is part of the educational point -- with PI "tethered" so the view
 * returns rather than letting someone get lost over open ocean. The tether
 * (see MapView) is what makes the wider rectangle safe; without it this would
 * just be the old "user wanders off to another continent" problem.
 *
 * Format: [[west, south], [east, north]]
 */
export const MAX_BOUNDS: [[number, number], [number, number]] = [
  [26.0, 24.0], // SW -- western Egypt / northern Sudan
  [45.0, 39.0], // NE -- eastern Iraq / central Türkiye
];

/** Floor on zoom. Lowered with the wider MAX_BOUNDS so the regional context
 * Bill asked for (Cyprus/Türkiye/Saudi/Egypt) actually fits on screen. */
export const MIN_ZOOM = 4.5;

/** Ceiling on zoom. Capped at 15 because Mapbox satellite-v9 tile coverage
 * in the PI region isn't reliable above ~z16 (Bill hit "Failed to fetch"
 * tile errors at z16). z15 = ~5 m/px which is more than enough detail for
 * neighbourhood-level editing. */
export const MAX_ZOOM = 15;

/**
 * How close, in SCREEN PIXELS, a stroke's endpoint must be to the PI outer
 * boundary for auto-complete to trace the border rather than close straight.
 *
 * Screen pixels, not kilometres, because this is a hand-eye judgement: the user
 * aims at a line they can see. Expressing the tolerance as a fixed ground
 * distance made it behave completely differently depending on zoom -- the old
 * fixed 1 km worked out to under one pixel at the default framing (z 6.7,
 * ~1284 m/px), so auto-complete almost never fired there, yet to roughly 245
 * pixels at z15, where it fired on strokes that ended nowhere near the border.
 * That is the erratic "sometimes it follows the boundary, sometimes it does
 * not" behaviour reported in testing.
 *
 * Note this governs only WHETHER auto-complete triggers, and where along the
 * border the trace begins and ends. It has no bearing on how faithfully the
 * traced edge follows the boundary -- that is now exact at every zoom.
 */
export const BOUNDARY_SNAP_PX = 20;

/** Clamp on the derived ground distance, so the tolerance stays sane at the
 * extremes of the zoom range.
 *
 * The ceiling used to be 10 km, which quietly defeated the whole point of
 * expressing the tolerance in pixels. Twenty screen pixels is ~19 km of ground
 * at the canonical framing, so the cap cut the tolerance in half exactly where
 * the tool opens -- and worse the further out you go: ~8 px at z6.7, ~5 px at
 * z6. Only from about z9 inward did the intended 20 px actually apply.
 *
 * That is the asymmetry Bill kept hitting. Zoomed in, aiming at the border
 * worked "very very well"; at the default view he had to land within ~10 px of
 * a 1.5 px-wide line, and every miss fell back silently to a straight closing
 * edge with no indication why. Raising the ceiling lets the pixel rule hold
 * across the whole range anyone actually draws at.
 */
export const BOUNDARY_SNAP_MIN_KM = 0.25;
export const BOUNDARY_SNAP_MAX_KM = 30;

/**
 * Convert {@link BOUNDARY_SNAP_PX} into a ground distance at the current zoom.
 * Uses the Web Mercator resolution at the given latitude.
 */
export function boundarySnapKm(zoom: number, latitude: number): number {
  const metresPerPx =
    (156543.03392 * Math.cos((latitude * Math.PI) / 180)) / Math.pow(2, zoom);
  const km = (metresPerPx * BOUNDARY_SNAP_PX) / 1000;
  return Math.min(BOUNDARY_SNAP_MAX_KM, Math.max(BOUNDARY_SNAP_MIN_KM, km));
}
