/**
 * A bridge member is a true-metre object, and every board has to agree.
 *
 * `size(metres, floor)` used to take `floor` in scene units, tuned at 94 m to
 * the unit. On the merged California board (1,919 m/unit) those floors always
 * won: a 21 m deck half became 173 m, and the Golden Gate read as a highway.
 * The floor is metres now. This is the property that would have caught it:
 * two boards twenty times apart draw the same deck width on the ground.
 */

import assert from "node:assert/strict";
import test from "node:test";

import { planBridge } from "../../engine/bridges.ts";
import type { Bridge } from "../../engine/types.ts";
import type { World } from "../../engine/world.ts";

const GOLDEN_GATE: Bridge = {
  name: "Golden Gate Bridge",
  path: [
    [37.8025, -122.4752],
    [37.8155, -122.4783],
    [37.825, -122.479],
    [37.8375, -122.4806],
  ],
  towers: [
    [37.8155, -122.4783],
    [37.825, -122.479],
  ],
  towerHeight: 227,
  deckHeight: 67,
  sag: 0.55,
  color: 0xc0442c,
};

function board(latScale: number): World {
  const centre = { lat: 37.7749, lng: -122.4194 };
  const lngScale = latScale * Math.cos((centre.lat * Math.PI) / 180);
  const metresPerUnit = 111_320 / latScale;
  return {
    project(lat: number, lng: number): [number, number] {
      return [(lng - centre.lng) * lngScale, -(lat - centre.lat) * latScale];
    },
    groundAt(): number {
      return 0;
    },
    metres(value: number): number {
      return value / metresPerUnit;
    },
    metresPerUnit,
  } as unknown as World;
}

test("the Golden Gate's deck is the same width on a 94 m board and a 1,919 m one", () => {
  const metro = planBridge(board(1180), GOLDEN_GATE);
  const state = planBridge(board(58), GOLDEN_GATE);
  assert.ok(
    Math.abs(metro.deckHalfMetres - state.deckHalfMetres) < 0.5,
    `deck half is ${metro.deckHalfMetres.toFixed(1)} m on the Bay and ` +
      `${state.deckHalfMetres.toFixed(1)} m on California`,
  );
  assert.ok(
    metro.deckHalfMetres > 15 && metro.deckHalfMetres < 30,
    `deck half measures ${metro.deckHalfMetres.toFixed(1)} m; that is not a highway`,
  );
});
