/**
 * Where the shipped buildings stand, separately from the buildings themselves.
 *
 * An `Office` pack carries its own `site`, and that is still the authority — a
 * pack handed over HTTP by a self-hoster brings its site with it and never
 * touches this file. What this file exists for is the one question the *city*
 * asks, which a pack cannot answer without being loaded: **where are the
 * buildings I could walk into?**
 *
 * The office packs are deliberately lazy chunks. `lumbridge-hq` alone is 25 kB
 * of furniture and floor plan, and the whole point of `loadOffice`'s dynamic
 * import is that a visitor who only ever looks at the city never pays for it.
 * But the city wants to draw a marker on the two buildings the moment the board
 * appears, which is long before anybody has opened a door — so importing a pack
 * to read four numbers off it would put the entire catalogue back in the entry
 * chunk and undo the split.
 *
 * Hence a tiny eagerly-imported module holding just the coordinates, and each
 * pack importing its own site **from here** rather than declaring it inline. One
 * source of truth, and the direction of the dependency is the safe one: the
 * small thing does not know about the large one.
 *
 * ### Where the car stands
 *
 * Each site below carries an `arrival` anchor: one marked stall on the ground
 * outside, in **the pack's own plan frame**, which is the only frame a pack has
 * and the same one its walls are in. `src/engine/officeExterior.ts` builds the
 * apron and the vehicle there.
 *
 * Two of the three are honest ground. `mateo-court` sits 1.2 m above its street
 * and `frontier-valley` 4 m above an airfield, so a stall a few metres outside
 * the façade is a stall on the pavement, and both get a kerb, a bay and a car.
 *
 * **`lumbridge-hq` is 188 m up a tower** and there is no pavement outside its
 * west wall at all. Its anchor is still true — a podium kerb does exist at the
 * foot of that tower — but the only frame a pack can say it in is a storey 188 m
 * above it, and an earlier build took that literally and parked a Model X in
 * open sky beside the studio wall. The anchor stays; the exterior layer now
 * declines to draw an apron for a site whose arrival storey is not on the
 * ground, on the strength of `elevation` alone. See `ArrivalGround` in
 * `src/transport/exteriorVehicle.ts` for the rule and for the two other repairs
 * that were weighed against it.
 *
 * This file states the coordinate and never the decision. What is "outside" for
 * a tower is architecture, and architecture belongs to the layer that renders
 * it — which is also why the rule reads `site.elevation` and not `id`.
 */

import type { OfficeSite } from "../interiors/types.ts";

/**
 * High in a Transbay tower. See `lumbridge-hq.ts` for what the four numbers mean
 * and why `heading` is the one that decides whether the sun ever gets in.
 */
export const LUMBRIDGE_HQ_SITE: OfficeSite = {
  lat: 37.7897,
  lng: -122.3972,
  elevation: 188,
  heading: 205,
  label: "Transbay, San Francisco",
  exterior: {
    kind: "building",
    width: 48,
    depth: 42,
    height: 326,
    storeys: 61,
    heading: 205,
    profile: "tower",
    seed: 115,
    bodyColor: 0x8799a8,
  },
  // The podium kerb at the foot of the tower: parallel to the façade and nosed
  // north, the way a kerbside bay on a one-way downtown street runs, and placed
  // west of the studio's own front door (the doorway 6.8 m along `ext-west`)
  // because a pack has no frame but its own to say it in.
  //
  // **Nothing renders here.** `elevation: 188` above puts this storey's floor
  // that far over the pavement, and `officeExterior.ts` builds no apron for a
  // site off the ground — so this is the address of a kerb rather than the
  // position of a car, and the field is kept because the telemetry layer and
  // `Plan.exteriorArrival` both read it and because the kerb is real. See the
  // note at the top of this file.
  arrival: {
    levelId: "level-1",
    position: { x: -4.0, z: 7.4 },
    rotation: 0,
    kind: "vehicle-stall",
    label: "Podium kerb",
  },
};

/** A hangar on the old naval air station. See `frontier-valley.ts`. */
export const FRONTIER_VALLEY_SITE: OfficeSite = {
  lat: 37.7756,
  lng: -122.3186,
  elevation: 4,
  heading: 0,
  label: "Alameda Point",
  exterior: {
    kind: "building",
    width: 54,
    depth: 30,
    height: 11,
    storeys: 2,
    heading: 0,
    profile: "hangar",
    seed: 2718,
    bodyColor: 0x899397,
  },
  // On the apron, seven metres clear of the twelve-metre hangar door in the east
  // gable and centred on it, nosed in. An apron is the one place in these three
  // packs where a vehicle is not a visitor but part of the programme.
  arrival: {
    levelId: "level-1",
    position: { x: 61.0, z: 12.0 },
    rotation: Math.PI / 2,
    kind: "vehicle-stall",
    label: "Hangar apron",
  },
};

/**
 * A courtyard block in the Arts District, square to the pueblo grid rather than
 * to the compass — which is the whole reason `heading` is a field. See
 * `mateo-court.ts` for where the numbers come from: 1.2 m is a loading dock, and
 * 36° is the 1781 survey the downtown street grid still follows.
 */
export const MATEO_COURT_SITE: OfficeSite = {
  lat: 34.0395,
  lng: -118.2288,
  elevation: 1.2,
  heading: 36,
  label: "Arts District, Los Angeles",
  exterior: {
    kind: "building",
    width: 36,
    depth: 26,
    height: 9,
    storeys: 2,
    heading: 36,
    profile: "courtyard",
    seed: 1781,
    bodyColor: 0xa87960,
  },
  // On the street, north of the brick façade and a few metres east of the paseo
  // arch, so that it is in frame from the arrival viewpoint and three steps from
  // the front door. `z` is negative because the street façade is authored at
  // `z = 0` and the pavement is on the other side of it, which is the whole
  // reason the anchor is in the plan's frame rather than the world's.
  arrival: {
    levelId: "level-1",
    position: { x: 22.6, z: -3.4 },
    rotation: -Math.PI / 2,
    kind: "vehicle-stall",
    label: "Mateo Street kerb",
  },
};

/**
 * Every building this build can walk into, for the city to point at.
 *
 * `id` matches the pack's own `Office.id` and the `OFFICES` table in `main.ts`,
 * which is what lets a click on a marker resolve to a door. Keeping the three in
 * step is not enforced by the type system; it is enforced by there being three of
 * them and by `office.test.ts` asserting that each pack's site is the very
 * object named here — identity, not equality, so a restated coordinate fails.
 */
export const SHIPPED_OFFICE_IDS = ["lumbridge-hq", "frontier-valley", "mateo-court"] as const;

export type ShippedOfficeId = (typeof SHIPPED_OFFICE_IDS)[number];
export type OfficeStatus = "active" | "building";

/**
 * The public, eager metadata for one shipped environment.
 *
 * `status` is about the authored runtime, not a lease or a headcount. `active`
 * means the environment is ready to enter; it never implies that people are in
 * the building. `entryCopy` is intentionally operational and contains no
 * invented street address or staffing claim.
 */
export interface OfficeDirectoryEntry {
  id: ShippedOfficeId;
  name: string;
  status: OfficeStatus;
  entryCopy: string;
  site: OfficeSite;
}

export const OFFICE_SITES: readonly OfficeDirectoryEntry[] = [
  {
    id: "lumbridge-hq",
    name: "SF HQ · Studio",
    status: "active",
    entryCopy: "Enter the compact live/work studio",
    site: LUMBRIDGE_HQ_SITE,
  },
  {
    id: "frontier-valley",
    name: "Frontier Valley",
    status: "building",
    entryCopy: "Preview the hangar environment in progress",
    site: FRONTIER_VALLEY_SITE,
  },
  {
    id: "mateo-court",
    name: "LA HQ · Office",
    status: "active",
    entryCopy: "Enter the courtyard office and robotics lab",
    site: MATEO_COURT_SITE,
  },
];

export function officeDirectoryEntry(id: string): OfficeDirectoryEntry | undefined {
  return OFFICE_SITES.find((entry) => entry.id === id);
}
