#!/usr/bin/env bash
# Launch the AGI interpreter in the named platform's emulator with a
# staged AGI v2 game directory. The game's data files are copied flat
# alongside the binary so AGI's CWD-relative default ("./LOGDIR" etc.)
# works on platforms whose autostart can't pass argv.
#
#   scripts/run-agi.sh <platform> [game] [room]
#     platform : dos | amiga | atarist | iigs
#     game     : subdirectory under examples/agi/gamedata/ (default kq3)
#     room     : starting room number 1..255. Skips logic.0's hardcoded
#                title-room target and jumps straight to the named room.
#                Only forwarded to DOS today -- the Atari ST / Amiga
#                autostart paths can't pass argv to the binary; their
#                AGI starts at the title screen until we wire a stage-
#                time config-file fallback or implement enough title
#                opcodes for the title to advance on its own.
#
# Required files in the game directory (others are ignored):
#   LOGDIR PICDIR VIEWDIR SNDDIR VOL.0 [VOL.1 ...] [OBJECT] [WORDS.TOK]
#
# IIgs delegates to run-iigs.sh's AGI mode, which packs AGI + the game
# onto a 2MB CFFA2 hard-disk volume (an 800KB floppy can't hold both) and
# boots GS/OS from a second CFFA2 partition. See make-agi-iigs-disk.sh.

set -euo pipefail

if [[ $# -lt 1 || $# -gt 3 ]]; then
    echo "usage: $0 <dos|amiga|atarist|iigs> [game-name] [starting-room]" >&2
    exit 2
fi

platform=$1
game=${2:-kq3}
room=${3:-0}

if ! [[ $room =~ ^[0-9]+$ ]] || (( room > 255 )); then
    echo "starting-room must be 0..255 (got '$room')" >&2
    exit 2
fi

repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
gamedata=$repo/examples/agi/gamedata/$game
support=$repo/toolchains/emulators/support

if [[ ! -d $gamedata ]]; then
    echo "$gamedata: not an AGI v2 game directory" >&2
    if [[ -d $repo/examples/agi/gamedata ]]; then
        echo "available games:" >&2
        find "$repo/examples/agi/gamedata" -maxdepth 1 -mindepth 1 -type d -printf '  %f\n' >&2
    fi
    exit 1
fi
if [[ ! -f $gamedata/LOGDIR ]]; then
    echo "$gamedata: no LOGDIR -- not an AGI v2 game directory" >&2
    exit 1
fi


# stageGameData WORKDIR
# Copies the subset of files AGI v2 reads (DIR files, VOL.x, OBJECT,
# WORDS.TOK) into WORKDIR. Leaves Sierra's original AGI binary, OVL
# graphics drivers, and platform-specific launchers behind so a flat
# stage doesn't clash with our binary's name on case-insensitive
# filesystems (e.g. Amiga FFS: "AGI" vs our "Agi").
stageGameData() {
    local destDir=$1
    local dataDir=$destDir/DATA
    local f

    # JoeyLib forces every data-file open under DATA/ (jlDataOpen), so the
    # AGI resources are staged into a DATA subdirectory of the mount root.
    mkdir -p "$dataDir"
    for f in LOGDIR PICDIR VIEWDIR SNDDIR OBJECT WORDS.TOK; do
        if [[ -f $gamedata/$f ]]; then
            cp "$gamedata/$f" "$dataDir/$f"
        fi
    done
    for f in "$gamedata"/VOL.*; do
        [[ -f $f ]] && cp "$f" "$dataDir/$(basename "$f")"
    done
}


runDos() {
    local bin=$repo/build/dos/bin/AGI.EXE
    local conf=$repo/scripts/dosbox-386sx16.conf
    local work

    if [[ ! -f $bin ]]; then
        echo "$bin not built. Run 'make -f make/dos.mk $bin' first." >&2
        exit 1
    fi

    # Sweep any leftover staging dirs from previous runs that
    # didn't reach their trap (DOSBox window close, SIGKILL, etc.).
    # We're about to make a new one anyway; freshly leftover dirs
    # serve no purpose and just leak ~1 MB each.
    rm -rf /tmp/joeylib-agi-dos.* 2>/dev/null || true
    rm -f  /tmp/joeylib-agi-dos-last.log    2>/dev/null || true

    work=$(mktemp -d -t joeylib-agi-dos.XXXXXX)
    # Cleanup trap: copy DJGPP's diagnostic log out (DOS uppercases
    # so the file lands as JOEYLOG.TXT, not joeylog.txt), then nuke
    # the staging dir. Hook EXIT plus the common interrupt signals
    # so the cleanup fires even when the user closes the DOSBox
    # window or Ctrl-Cs the terminal -- both bypass plain EXIT in
    # some bash configurations.
    cleanupDos() {
        local log
        for log in "$work/JOEYLOG.TXT" "$work/joeylog.txt"; do
            if [[ -f $log ]]; then
                cp "$log" /tmp/joeylib-agi-dos-last.log
                break
            fi
        done
        rm -rf "$work"
    }
    trap cleanupDos EXIT INT TERM HUP

    cp "$bin" "$work/AGI.EXE"
    stageGameData "$work"

    # AGI.EXE reads game data from DATA/ under its CWD (we mount $work as C:
    # and cd there first), so no game-directory argument is needed; the
    # starting-room override is argv[1]. Skip it when room=0 so the binary
    # exercises its default code path.
    local agi_cmd="AGI.EXE"
    if (( room != 0 )); then
        agi_cmd="AGI.EXE $room"
    fi

    cat <<EOF
DOSBox: mounting $work as C:, running '$agi_cmd' for $game.
ESC quits the demo, then 'pause' waits for a keypress in the shell.
EOF

    local dosboxArgs=(
        -conf "$conf"
        -set "mouse_capture=seamless"
    )
    # CYCLES=max (or any other DOSBox cycles value) overrides the conf's
    # period-correct 386SX-16 cap. Use this to A/B test whether perf
    # ceilings are coming from the simulated CPU or the code itself.
    if [[ -n "${CYCLES:-}" ]]; then
        dosboxArgs+=(-set "cpu cycles=$CYCLES")
    fi
    dosboxArgs+=(
        -c "C:"
        -c "$agi_cmd"
        -c "pause"
        --exit "$work"
    )
    # Avoid `exec`: we need bash to stay alive so the EXIT trap above
    # actually runs and removes the staged $work dir. With `exec`,
    # dosbox replaces the shell and the trap never fires, leaking
    # ~1 MB of game data into /tmp on every launch.
    dosbox "${dosboxArgs[@]}"
}


runAtariST() {
    local bin=$repo/build/atarist/bin/AGI.PRG
    local tos=$support/emutos-512k.img
    local work

    if [[ ! -f $bin ]]; then
        echo "$bin not built. Run 'make -f make/atarist.mk $bin' first." >&2
        exit 1
    fi
    if [[ ! -f $tos ]]; then
        echo "TOS ROM missing: $tos" >&2
        echo "Run ./toolchains/install.sh (EmuTOS should have been staged)." >&2
        exit 1
    fi

    rm -rf /tmp/joeylib-agi-atarist.* 2>/dev/null || true
    work=$(mktemp -d -t joeylib-agi-atarist.XXXXXX)
    trap 'rm -rf "$work"' EXIT INT TERM HUP

    cp "$bin" "$work/AGI.PRG"
    stageGameData "$work"

    cat <<EOF
Hatari: mounting $work as GEMDOS C:, autostarting AGI.PRG for $game.
EOF

    # Run hatari as a child so the EXIT trap removes the staged
    # game data dir; `exec` would have hatari replace bash and
    # leak $work into /tmp on every launch.
    hatari \
        --tos         "$tos" \
        --harddrive   "$work" \
        --gemdos-drive C \
        --auto        "C:\\AGI.PRG"
}


runAmiga() {
    local bin=$repo/build/amiga/bin/Agi
    local kickstart=$support/kickstart.rom
    local workbench=$support/workbench.adf
    local work

    if [[ ! -f $bin ]]; then
        echo "$bin not built. Run 'make -f make/amiga.mk $bin' first." >&2
        exit 1
    fi

    rm -rf /tmp/joeylib-agi-amiga.* 2>/dev/null || true
    work=$(mktemp -d -t joeylib-agi-amiga.XXXXXX)
    trap 'rm -rf "$work"' EXIT INT TERM HUP

    mkdir -p "$work/s"
    cp "$bin" "$work/Agi"
    stageGameData "$work"
    # ':' prefix anchors to volume root so AmigaDOS doesn't search C:.
    echo ":Agi" > "$work/s/startup-sequence"

    local fsargs=(
        --amiga_model=A500
        --fast_memory=2048
        --hard_drive_0="$work"
        --hard_drive_0_label=JOEYLIB
        --automatic_input_grab=0
        --middle_click_ungrab=1
        --mouse_integration=1
        --floppy_drive_speed=800
    )
    if [[ -f $kickstart ]]; then
        fsargs+=(--kickstart_file="$kickstart")
    fi

    if [[ -f $workbench ]]; then
        # If a Workbench floppy is staged it boots from DF0: instead of
        # the HD, so the startup-sequence never fires. Skip Workbench
        # for AGI to keep the launch one-shot; user can still launch
        # manually with run-amiga.sh if they want the GUI.
        echo "(skipping workbench.adf so the JOEYLIB HD boots Agi directly)"
    fi

    cat <<EOF
FS-UAE booting JOEYLIB hard drive ($work) and auto-running Agi for $game.
EOF

    fs-uae "${fsargs[@]}"
}


runIigs() {
    # IIgs uses a CFFA2 hard disk (the 800KB floppy can't hold AGI + KQ3),
    # driven entirely by run-iigs.sh's AGI mode. Delegate to it: it builds
    # the two-partition CFFA image via make-agi-iigs-disk.sh, boots GS/OS,
    # and launches AGI. The starting-room override is DOS-only (the IIgs
    # autostart path can't pass argv), so $room is not forwarded here.
    if (( room != 0 )); then
        echo "note: starting-room override is DOS-only; ignored on IIgs" >&2
    fi
    # The IIgs build target is the binary path, not EXAMPLE=agi.
    if [[ ! -f "$repo/build/iigs/bin/AGI" ]]; then
        echo "$repo/build/iigs/bin/AGI not built." >&2
        echo "Build it with: make -f make/iigs.mk $repo/build/iigs/bin/AGI" >&2
        exit 1
    fi
    JOEY_AGI_GAME="$game" exec "$repo/scripts/run-iigs.sh" agi
}


case "$platform" in
    dos)     runDos ;;
    atarist) runAtariST ;;
    amiga)   runAmiga ;;
    iigs)    runIigs ;;
    *)
        echo "$platform: unknown platform (expected dos, amiga, atarist, or iigs)" >&2
        exit 2
        ;;
esac
