#!/bin/bash
# AAhead (shell) — PortMaster launcher (pygame GUI).
# Mirrors the proven R36S Manager / devilutionx path on this device:
#   - run as the normal user (NOT sudo) so DRM master / EGL works
#   - use /dev/tty1, chmod uinput, keep SDL_GAMECONTROLLERCONFIG
#   - shim the bundled pygame SDL → system SDL2 (Mali EGL/GBM linkage)
#   - drive input via gptokeyb (gamepad → keyboard) which pygame reads
# Play is real now: the shell resolves a game via es_systems.cfg, writes a
# .launch flag + exits, and the loop below runs the emulator and returns.

XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}

if [ -d "/opt/system/Tools/PortMaster/" ]; then
  controlfolder="/opt/system/Tools/PortMaster"
elif [ -d "/opt/tools/PortMaster/" ]; then
  controlfolder="/opt/tools/PortMaster"
elif [ -d "$XDG_DATA_HOME/PortMaster/" ]; then
  controlfolder="$XDG_DATA_HOME/PortMaster"
else
  controlfolder="/roms/ports/PortMaster"
fi

GAMEDIR="$(cd "$(dirname "$0")" && pwd)"
LOG="$GAMEDIR/gui.log"
exec >> "$LOG" 2>&1
: > "$LOG"
echo "==== AAhead launch $(date) ===="
sync

source "$controlfolder/control.txt"
[ -f "$controlfolder/device_info.txt" ] && source "$controlfolder/device_info.txt"
[ -f "${controlfolder}/mod_${CFW_NAME}.txt" ] && source "${controlfolder}/mod_${CFW_NAME}.txt"
get_controls

if [ -n "$directory" ] && [ -d "/$directory/ports/aahead" ]; then
  GAMEDIR="/$directory/ports/aahead"
fi
cd "$GAMEDIR" || { echo "FATAL: cannot cd $GAMEDIR"; exit 1; }

DEVICE_ARCH="${DEVICE_ARCH:-aarch64}"
echo "step: env GAMEDIR=$GAMEDIR arch=$DEVICE_ARCH user=$(id -un)($(id -u))"

$ESUDO chmod 666 /dev/tty1 2>/dev/null
$ESUDO chmod 666 /dev/uinput 2>/dev/null

if [ -z "${XDG_RUNTIME_DIR:-}" ] || [ ! -d "$XDG_RUNTIME_DIR" ] || [ ! -w "$XDG_RUNTIME_DIR" ]; then
  export XDG_RUNTIME_DIR="/tmp/runtime-$(id -u)"
  mkdir -p "$XDG_RUNTIME_DIR"; chmod 700 "$XDG_RUNTIME_DIR" 2>/dev/null || true
fi

setup_system_sdl() {
  local wheel_libdir="$GAMEDIR/gui/vendor/pygame_ce.libs"
  local wheel_sdl_name="libSDL2-2-fa51324d.0.so.0.3200.10"
  local wheel_sdl="$wheel_libdir/$wheel_sdl_name"
  local wheel_sdl_backup="$wheel_sdl.pygame-wheel"
  local shim_dir="/tmp/aahead-sdl"
  local system_sdl="" candidate
  for candidate in \
    "/usr/lib/${DEVICE_ARCH}-linux-gnu/libSDL2-2.0.so.0.3200.10" \
    "/usr/lib/${DEVICE_ARCH}-linux-gnu/libSDL2-2.0.so.0" \
    "/lib/${DEVICE_ARCH}-linux-gnu/libSDL2-2.0.so.0" \
    "/usr/lib/libSDL2-2.0.so.0"
  do
    [ -r "$candidate" ] && { system_sdl="$candidate"; break; }
  done
  if [ -z "$system_sdl" ]; then echo "step: system SDL not found; using wheel SDL"; return 0; fi
  echo "step: system SDL: $system_sdl"
  if [ -f "$wheel_sdl" ]; then
    if [ ! -f "$wheel_sdl_backup" ]; then
      mv "$wheel_sdl" "$wheel_sdl_backup" && echo "step: wheel SDL aside"
    else
      mv "$wheel_sdl" "$wheel_sdl.disabled.$(date +%s)"
    fi
  fi
  mkdir -p "$shim_dir"; rm -f "$shim_dir/$wheel_sdl_name"
  ln -s "$system_sdl" "$shim_dir/$wheel_sdl_name" 2>/dev/null \
    || cp -f "$system_sdl" "$shim_dir/$wheel_sdl_name"
  export LD_LIBRARY_PATH="$shim_dir:${LD_LIBRARY_PATH:-}"
}
setup_system_sdl

export PYTHONPATH="$GAMEDIR/gui/vendor:$PYTHONPATH"
export ESUDO="${ESUDO:-sudo}"
export SDL_GAMECONTROLLERCONFIG="$sdl_controllerconfig"
export R36S_FULLSCREEN=1
export SDL_VIDEODRIVER="${SDL_VIDEODRIVER:-kmsdrm}"
unset SDL_FRAMEBUFFER_ACCELERATION

# AAhead Control live backend (was exported by the legacy port launcher; lost
# in the repo split). Turns the Settings module's device features real:
#   • Wi-Fi  → nmcli directly (gui/control/netops.py), present on dArkOS
#   • Bluetooth → aactl job server at $GAMEDIR/aactl, IF shipped
# Default-on for the device, still overridable. Safe without the tools: each
# backend call degrades to None (→ the screen keeps its demo data), so a
# missing aactl or nmcli never crashes Control.
export AAHEAD_LIVE_BACKEND="${AAHEAD_LIVE_BACKEND:-1}"
export AAHEAD_AACTL="${AAHEAD_AACTL:-$GAMEDIR/aactl}"

echo "step: launch GUI (as user, no sudo)"
sync
# One app: game + Settings (AAhead Control) in-process. The ONLY out-of-process
# step is the controller remap — it needs gptokeyb OFF to read the raw joystick.
# The app leaves a .open-remap flag and exits; we run --remap WITHOUT gptokeyb,
# then loop straight back to the normal in-process app.
rm -f "$GAMEDIR/.open-remap"
while true; do
  if [ -n "$GPTOKEYB" ]; then
    echo "step: start gptokeyb"
    $GPTOKEYB "python3" -c "$GAMEDIR/aahead.gptk" &
  else
    echo "step: GPTOKEYB unset — relying on native joystick"
  fi
  python3 -u "$GAMEDIR/gui/main.py"
  echo "GUI exited rc=$?"
  $ESUDO kill -9 "$(pidof gptokeyb)" 2>/dev/null
  sync
  if [ -f "$GAMEDIR/.open-remap" ]; then
    rm -f "$GAMEDIR/.open-remap"
    echo "step: controller remap (no gptokeyb)"
    python3 -u "$GAMEDIR/gui/main.py" --remap
    echo "remap exited rc=$?"
    sync
    continue
  fi
  # Game launch: the shell resolved a game → wrote its emulator command here, then
  # exited. gptokeyb is already killed above, so the emulator owns the pad. Run it,
  # then loop straight back into the shell (seamless return).
  #
  # Flag format (per Step E):
  #   line 1: the shell command to run (the resolved emulator invocation)
  #   line 2: optional `MODE=restart` — the user picked "Restart" instead of
  #           Continue, so the emulator's auto-state load must be skipped.
  # Older shells write only line 1; absence of line 2 means Continue (default).
  if [ -f "$GAMEDIR/.launch" ]; then
    GAME_CMD="$(head -n1 "$GAMEDIR/.launch")"
    GAME_MODE="$(sed -n 's/^MODE=//p' "$GAMEDIR/.launch" | head -n1)"
    rm -f "$GAMEDIR/.launch"
    echo "step: launch game (mode=${GAME_MODE:-continue}): $GAME_CMD"
    if [ "$GAME_MODE" = "restart" ]; then
      # TODO (E.2, on-device): identify and delete the emulator's autosave for
      # this ROM (RetroArch: `${rom_basename}.state.auto` next to the savestate
      # dir, paths vary per device). Until then, Restart is a logged intent,
      # not yet enforced — the emulator's auto-load still wins.
      echo "step: RESTART requested — autosave-drop is pending (E.2, device)"
    fi
    # ── Cheat diagnostic: log every .cht that the shell wrote for this ROM
    #    and which RetroArch override cfg got --appendconfig'd. Helps
    #    diagnose why cheats did/didn't auto-apply on a given build.
    # Extract the ROM path from the command — `head -n1 .launch` may include
    # the dArkOS perfmax wrapper, so grep for the first /roms/... .ext token.
    ROM_PATH="$(echo "$GAME_CMD" | grep -oE "/roms/[^']+\.[a-zA-Z0-9]+" | head -n1)"
    if [ -n "$ROM_PATH" ]; then
      ROM_DIR="$(dirname "$ROM_PATH")"
      ROM_BASE="$(basename "${ROM_PATH%.*}")"
      echo "cheat-diag: ROM = $ROM_PATH"
      # Scan every plausible auto-load path — the canonical one (per
      # cheat_manager_get_game_specific_filename in RA source) lives under
      # /roms/cheats/<library_name>/<basename>.cht where library_name comes
      # from the core's retro_get_system_info (e.g. "Genesis Plus GX").
      while IFS= read -r p; do
        if [ -f "$p" ]; then
          on_count="$(grep -c '_enable = true' "$p" 2>/dev/null || echo 0)"
          echo "cheat-diag:   $p   (${on_count} enabled)"
        fi
      done <<EOF
$ROM_DIR/$ROM_BASE.cht
/roms/cheats/$ROM_BASE.cht
/roms/cheats/Genesis Plus GX/$ROM_BASE.cht
/roms/cheats/Snes9x/$ROM_BASE.cht
/roms/cheats/mGBA/$ROM_BASE.cht
/roms/cheats/Gambatte/$ROM_BASE.cht
/roms/cheats/Nestopia/$ROM_BASE.cht
/roms/cheats/Mupen64Plus-Next/$ROM_BASE.cht
/roms/cheats/PCSX-ReARMed/$ROM_BASE.cht
/roms/cheats/PicoDrive/$ROM_BASE.cht
/roms/cheats/PPSSPP/$ROM_BASE.cht
/roms/cheats/FinalBurn Neo/$ROM_BASE.cht
EOF
    fi
    # Also dump the override cfg the shell appended — confirms our display
    # preset + cheats_apply hints reach the emulator's config.
    OVERLAY_CFG="$(echo "$GAME_CMD" | grep -oE -- '--appendconfig\s+\S+' | head -n1 | awk '{print $2}')"
    if [ -n "$OVERLAY_CFG" ] && [ -f "$OVERLAY_CFG" ]; then
      echo "cheat-diag: override cfg = $OVERLAY_CFG"
      sed 's/^/cheat-diag:   /' "$OVERLAY_CFG"
    fi
    sync
    bash -c "$GAME_CMD"
    echo "game exited rc=$?"
    sync
    continue
  fi
  break
done

printf "\033c" >> /dev/tty1 2>/dev/null
$ESUDO systemctl restart oga_events 2>/dev/null &
