#!/usr/bin/env bash
# Linux Game Bench - Steam Deck installer (also for ROG Ally, Legion Go, MSI Claw, AYANEO, GPD and ONEXPLAYER).
# Read it first if you like:   curl -fsSL https://linuxgamebench.com/deck.sh | less
# Everything is installed into your home folder (SteamOS updates do not touch it):
#   ~/Applications/LinuxGameBench.AppImage     the program
#   ~/.config/systemd/user/lgb-deck.service    the background recorder
#   ~/.config/MangoHud/MangoHud.conf           invisible logging config
#   ~/.local/share/lgb/deck/                   recordings waiting to be uploaded
# Remove it again with:   ~/Applications/LinuxGameBench.AppImage deck remove
# Account: optional. The install file of the website sets one of these for you -
#   LGB_LINK_TICKET=<key>   link the account the visitor was logged in with (one-time key, 30 minutes)
#   LGB_ANON=1              no account, no question
# With neither, the setup offers a short code to approve on your phone/PC (Enter skips it).
set -euo pipefail

BASE="${LGB_BASE:-https://linuxgamebench.com}"
APP_DIR="${LGB_APP_DIR:-$HOME/Applications}"
APP="$APP_DIR/LinuxGameBench.AppImage"
IMAGE="LinuxGameBench-x86_64.AppImage"

say() { printf '%s\n' "$*"; }
die() { printf '\nError: %s\n' "$*" >&2; exit 1; }

[ "$(id -u)" -ne 0 ] || die "Run this as the normal Deck user, not as root."
[ "$(uname -m)" = "x86_64" ] || die "This installer is for x86_64 machines (the Steam Deck and other PC handhelds)."
command -v curl >/dev/null 2>&1 || die "curl is missing."
command -v sha256sum >/dev/null 2>&1 || die "sha256sum is missing."

DMI_DIR="${LGB_DMI_DIR:-/sys/devices/virtual/dmi/id}"
dmi() { local f="$DMI_DIR/$1"; [ -r "$f" ] || return 0; tr -s ' \n' ' ' < "$f" | sed 's/^ //; s/ $//'; }
model="$(dmi product_name)"
vendor="$(dmi sys_vendor | tr 'A-Z' 'a-z')"
text="$(printf '%s %s' "$model" "$(dmi product_version)" | tr 'A-Z' 'a-z')"
# Other handhelds are recognised by the vendor and product name the firmware reports - the same table the website uses.
# Only the Steam Deck is verified on real hardware.
match() { printf '%s' "$vendor" | grep -Eq "$1" && printf '%s' "$text" | grep -Eq "$2"; }
handheld=""
if   match 'asus' 'xbox ally|rc73[xy]a'; then handheld="ROG Xbox Ally"
elif match 'asus' 'rog ally x|rc72la'; then handheld="ROG Ally X"
elif match 'asus' 'rog ally|rc71l'; then handheld="ROG Ally"
elif match 'lenovo' 'legion go s\b|\b83(l3|n6|q2|q3)\b'; then handheld="Legion Go S"
elif match 'lenovo' 'legion go 2\b'; then handheld="Legion Go 2"
elif match 'lenovo' 'legion go\b|\b83e1\b'; then handheld="Legion Go"
elif match 'micro-star|\bmsi\b' '\bclaw\b'; then handheld="MSI Claw"
elif match 'ayaneo|aya neo|ayadevice' '.'; then handheld="AYANEO"
elif match '^gpd\b' '.'; then handheld="GPD"
elif match 'one-?netbook|onexplayer' '.'; then handheld="ONEXPLAYER"
fi
case "$model" in
  Jupiter) say "Steam Deck LCD detected." ;;
  Galileo) say "Steam Deck OLED detected." ;;
  *)
    if [ -n "$handheld" ]; then
      say "$handheld detected."
      say "(Only the Steam Deck is verified on real hardware - on this handheld some values may be missing. Please tell us what you find.)"
    elif [ "${LGB_FORCE:-0}" = "1" ]; then
      say "Not a known handheld (${model:-unknown}) - continuing because LGB_FORCE=1."
    else
      die "This does not look like a Steam Deck or another supported handheld (product: ${model:-unknown}). Set LGB_FORCE=1 to install anyway."
    fi ;;
esac
[ "${LGB_DETECT_ONLY:-0}" = "1" ] && exit 0

mkdir -p "$APP_DIR"
tmp="$(mktemp "$APP_DIR/.lgb-download.XXXXXX")"
trap 'rm -f "$tmp"' EXIT

say "Downloading Linux Game Bench (about 130 MB)..."
curl -fL --retry 6 --retry-delay 2 --retry-connrefused --progress-bar -o "$tmp" "$BASE/downloads/$IMAGE" \
  || die "Download failed. Are you online? ($BASE/downloads/$IMAGE)"

expected="$(curl -fsSL --retry 6 --retry-delay 2 --retry-connrefused "$BASE/downloads/$IMAGE.sha256" 2>/dev/null | cut -d' ' -f1 || true)"
actual="$(sha256sum "$tmp" | cut -d' ' -f1)"
if [ -n "$expected" ] && [ "$expected" != "$actual" ]; then
  die "The download is damaged (checksum differs). Nothing was installed - please try again."
fi
[ -n "$expected" ] || say "(no checksum available from the server - continuing)"

chmod +x "$tmp"
mv -f "$tmp" "$APP"
trap - EXIT
say "Installed: $APP"

# AppImages need FUSE; if it is missing, let the AppImage unpack itself on start instead.
if [ ! -e /dev/fuse ] || ! command -v fusermount >/dev/null 2>&1; then
  export APPIMAGE_EXTRACT_AND_RUN=1
fi

if [ "${LGB_NO_SETUP:-0}" = "1" ]; then
  say "Skipping setup (LGB_NO_SETUP=1). Run:  $APP deck setup"
  exit 0
fi

say ""
if [ "${LGB_FORCE:-0}" = "1" ]; then
  "$APP" deck setup --yes --force
else
  "$APP" deck setup --yes
fi
