/** Deterministic, renderer-independent authored detail for freeway corridors. */

import type { TransportPack } from "./types.ts";
import { buildRoutePath, sampleRoute } from "./vehicleSim.ts";

export type FreewayIdentity = "us-highway" | "interstate";
export type RoadsideFeatureKind = "oak" | "orchard" | "power-pole" | "silo" | "route-sign";

export interface FreewayWorldSample {
  distanceM: number;
  lat: number;
  lng: number;
  headingDeg: number;
  elevationPhase: number;
  lanesPerDirection: number;
}

export interface FreewayRoadsideFeature {
  id: string;
  kind: RoadsideFeatureKind;
  distanceM: number;
  side: -1 | 1;
  setbackM: number;
  scale: number;
}

export interface FreewayRoutePlan {
  routeId: string;
  identity: FreewayIdentity;
  shield: "101" | "5";
  character: "coastal-oak" | "central-valley";
  samples: readonly FreewayWorldSample[];
  roadside: readonly FreewayRoadsideFeature[];
}

export interface FreewayWorldPlan {
  seed: number;
  routes: readonly FreewayRoutePlan[];
}

function hash(value: string): number {
  let out = 2_166_136_261;
  for (let index = 0; index < value.length; index += 1) {
    out ^= value.charCodeAt(index);
    out = Math.imul(out, 16_777_619);
  }
  return out >>> 0;
}

function seeded(seed: number): () => number {
  let state = seed >>> 0;
  return () => {
    state += 0x6d2b79f5;
    let value = state;
    value = Math.imul(value ^ (value >>> 15), value | 1);
    value ^= value + Math.imul(value ^ (value >>> 7), value | 61);
    return ((value ^ (value >>> 14)) >>> 0) / 4_294_967_296;
  };
}

/**
 * Compile visual-world intent without Three.js or wall-clock state. The plan is
 * suitable for snapshots, replay provenance, server-side validation, and a
 * browser renderer. It intentionally derives only from the open transport pack.
 */
export function buildFreewayWorldPlan(
  pack: TransportPack,
  options: { seed?: number; sampleCount?: number } = {},
): FreewayWorldPlan {
  const seed = options.seed ?? 101_005;
  const sampleCount = Math.max(12, Math.min(128, Math.floor(options.sampleCount ?? 56)));
  const segments = new Map(pack.segments.map((segment) => [segment.id, segment]));
  const routes = pack.routes.map((route): FreewayRoutePlan => {
    const path = buildRoutePath(pack, route.id);
    const first = segments.get(route.segmentIds[0] ?? "");
    const identity: FreewayIdentity = first?.kind === "us-highway" ? "us-highway" : "interstate";
    const rand = seeded(seed ^ hash(route.id));
    const samples = Array.from({ length: sampleCount }, (_, index): FreewayWorldSample => {
      const distanceM = (index / (sampleCount - 1)) * path.lengthM;
      const sample = sampleRoute(path, distanceM);
      const segment = segments.get(sample.segmentId);
      return {
        distanceM,
        lat: sample.lat,
        lng: sample.lng,
        headingDeg: sample.headingDeg,
        // A reproducible visual grade cue. Actual ground height is supplied by
        // the renderer; this phase only varies berm/vegetation rhythm.
        elevationPhase: Math.sin(index * 0.43 + rand() * 0.35),
        lanesPerDirection: Math.max(2, Math.min(5, segment?.lanesPerDirection ?? 2)),
      };
    });
    const featureCount = identity === "us-highway" ? 96 : 88;
    const roadside = Array.from({ length: featureCount }, (_, index): FreewayRoadsideFeature => {
      const sign = index % 23 === 2;
      const power = identity === "interstate" && index % 4 === 0;
      const silo = identity === "interstate" && index % 13 === 7;
      const kind: RoadsideFeatureKind = sign
        ? "route-sign"
        : silo
          ? "silo"
          : power
            ? "power-pole"
            : identity === "us-highway" && index % 3 !== 1
              ? "oak"
              : "orchard";
      return {
        id: `${route.id}:${String(index).padStart(2, "0")}`,
        kind,
        distanceM: ((index + 0.7 + rand() * 0.45) / featureCount) * path.lengthM,
        side: rand() < 0.5 ? -1 : 1,
        setbackM: kind === "route-sign" ? 13 : 18 + rand() * 38,
        scale: 0.78 + rand() * 0.58,
      };
    });
    return {
      routeId: route.id,
      identity,
      shield: identity === "us-highway" ? "101" : "5",
      character: identity === "us-highway" ? "coastal-oak" : "central-valley",
      samples,
      roadside,
    };
  });
  return { seed, routes };
}
