import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
  cityControlOwnership,
  cityControlMode,
  createControlModeState,
  transitionControlMode,
} from "../play/controlMode.ts";

const OUTSIDE = {
  insideOffice: false,
  drive: true,
  actor: true,
  aircraft: true,
  officeWalk: false,
};

describe("exclusive play control mode", () => {
  it("assigns exactly one local camera writer in every city mode", () => {
    for (const mode of ["overview", "drive", "actor", "aircraft"] as const) {
      const ownership = cityControlOwnership(mode);
      assert.equal(Object.values(ownership).filter(Boolean).length, 1);
      assert.equal(ownership[mode === "overview" ? "orbit" : mode], true);
    }
    assert.equal(cityControlOwnership("drive").orbit, false);
  });

  it("changes exactly one owner and revisions accepted transitions", () => {
    let state = createControlModeState();
    const driving = transitionControlMode(state, "drive", OUTSIDE);
    assert.equal(driving.accepted, true);
    assert.equal(driving.changed, true);
    assert.deepEqual(driving.state, { mode: "drive", revision: 1 });
    state = driving.state;
    const aircraft = transitionControlMode(state, "aircraft", OUTSIDE);
    assert.deepEqual(aircraft.state, { mode: "aircraft", revision: 2 });
    assert.equal(aircraft.previous, "drive");
  });

  it("falls back safely when a requested subsystem is unavailable", () => {
    const unavailable = transitionControlMode(
      createControlModeState("drive"),
      "aircraft",
      { ...OUTSIDE, aircraft: false },
    );
    assert.equal(unavailable.accepted, false);
    assert.equal(unavailable.reason, "unavailable");
    assert.equal(unavailable.state.mode, "overview");
  });

  it("keeps office and city modes in disjoint places", () => {
    const office = { ...OUTSIDE, insideOffice: true, officeWalk: true };
    const entered = transitionControlMode(createControlModeState(), "office-walk", office);
    assert.equal(entered.state.mode, "office-walk");
    const rejected = transitionControlMode(entered.state, "drive", office);
    assert.equal(rejected.state.mode, "office-overview");
    assert.equal(cityControlMode(rejected.state.mode), "overview");
  });
});
