#!/bin/bash
# gpu-mode — the discrete-GPU lever for the ParVagues laptop (EnvyControl front-end).
#
# WHY this exists, separate from perf.sh: perf.sh modes (silent/cool/...) are
# INSTANT and reversible (governor, EPP, RAPL watt caps). Turning the dGPU off is
# NOT — it's a persistent config change that only takes effect after a re-login.
# On this Plasma-Wayland box Xwayland pins the RTX 2060 'active' no matter the
# runtime-PM settings, so hybrid+RTD3 never actually suspends it live; the only
# real dGPU-off is EnvyControl's 'integrated' mode (blacklists nvidia) + re-login.
# That's ~4-5 W and a chunk of idle heat reclaimed for Silent sets.
#
# Deliberately NOT in the passwordless perf-audio sudoers whitelist: this is a
# rare, considered, re-login-required switch — not something the web Bridge or the
# tray should ever fire unattended. Run it by hand, with your sudo password.

set -u

RED=$'\e[31m'; GRN=$'\e[32m'; YEL=$'\e[33m'; CYA=$'\e[36m'; BLD=$'\e[1m'; RST=$'\e[0m'
say()  { printf '%s\n' "$*"; }
info() { printf '%s%s%s\n' "$CYA" "$*" "$RST"; }
ok()   { printf '%s✓ %s%s\n' "$GRN" "$*" "$RST"; }
warn() { printf '%s! %s%s\n' "$YEL" "$*" "$RST"; }
die()  { printf '%s✗ %s%s\n' "$RED" "$*" "$RST" >&2; exit 1; }

command -v envycontrol >/dev/null 2>&1 || die "envycontrol not installed (pacman -S envycontrol)."

# Live runtime state of the dGPU (independent of the persistent manager mode).
dgpu_runtime() {
  local d cls vendor status
  for d in /sys/bus/pci/devices/*; do
    cls=$(cat "$d/class" 2>/dev/null) || continue
    case "$cls" in 0x0300*|0x0302*) ;; *) continue ;; esac
    vendor=$(cat "$d/vendor" 2>/dev/null)
    [ "$vendor" = "0x8086" ] && continue      # skip the Intel iGPU
    status=$(cat "$d/power/runtime_status" 2>/dev/null || echo "?")
    printf '%s (%s)' "$status" "$(basename "$d")"
    return
  done
  printf 'none on PCI'
}

show_status() {
  local mode; mode=$(envycontrol --query 2>/dev/null | tr -d '[:space:]')
  info "GPU manager mode : ${BLD}${mode:-unknown}${RST}${CYA}   (persistent; changes take effect after re-login)"
  info "dGPU runtime now : ${BLD}$(dgpu_runtime)${RST}"
  case "$mode" in
    integrated) ok  "dGPU is OFF after login — lowest heat/power. No CUDA/NVENC until you switch back to hybrid." ;;
    hybrid)     warn "dGPU present & driver-loaded; Xwayland keeps it 'active' on this box → run 'integrated' for a real off." ;;
    nvidia)     warn "dGPU-only mode — highest power. 'hybrid' or 'integrated' to save heat." ;;
  esac
}

confirm() {  # confirm "<prompt>"  — skipped with -y
  [ "${ASSUME_YES:-0}" = "1" ] && return 0
  local ans; printf '%s%s%s ' "$YEL" "$1 [y/N]" "$RST"; read -r ans
  case "$ans" in y|Y|yes|YES) return 0 ;; *) die "aborted." ;; esac
}

relogin_note() {
  say ""
  warn "Not live yet — the switch applies on the NEXT login."
  say  "  Safest: ${BLD}reboot${RST} (guarantees the nvidia modules load/unload cleanly)."
  say  "  Usually enough: log out and back in (Plasma → Leave → Log Out)."
  say  "  Verify after:  ${BLD}./gpu-mode.sh query${RST}  and  ${BLD}nvidia-smi${RST} (should fail in integrated)."
}

usage() {
  cat <<EOF
${BLD}gpu-mode${RST} — discrete-GPU lever (EnvyControl front-end)

Usage: $0 <command> [-y]

Commands:
  ${BLD}query${RST} | -q     Show manager mode + live dGPU runtime state (default)
  ${BLD}integrated${RST}     Turn the dGPU OFF (blacklist nvidia). Coolest/quietest;
                 loses CUDA/NVENC until you switch back. Needs re-login.
  ${BLD}hybrid${RST}         Restore the dGPU, runtime-D3 power-managed (--rtd3 3).
                 Needs re-login. (Note: Xwayland pins it 'active' live anyway.)

  -y             Skip the confirmation prompt (for scripting).

The switch itself runs 'sudo envycontrol ...' — you'll be asked for your password.
EOF
}

ASSUME_YES=0
CMD="query"
for a in "$@"; do
  case "$a" in
    -y|--yes) ASSUME_YES=1 ;;
    query|-q|--query) CMD="query" ;;
    integrated) CMD="integrated" ;;
    hybrid) CMD="hybrid" ;;
    -h|--help|help) usage; exit 0 ;;
    *) die "unknown argument: $a  (try -h)" ;;
  esac
done

case "$CMD" in
  query)
    show_status
    ;;
  integrated)
    show_status; say ""
    warn "This turns the dGPU OFF and blacklists the nvidia driver."
    say  "  • Coolest/quietest state — best for Silent sets."
    say  "  • You LOSE CUDA / NVENC (demucs & audio-ML GPU accel) until you run 'hybrid' again."
    confirm "Switch to integrated (dGPU off)?"
    sudo envycontrol -s integrated || die "envycontrol failed (see output above)."
    ok "EnvyControl set to integrated."
    relogin_note
    ;;
  hybrid)
    show_status; say ""
    info "Restoring hybrid mode with aggressive runtime-D3 (--rtd3 3 = D3cold when idle)."
    confirm "Switch to hybrid (dGPU back on, power-managed)?"
    sudo envycontrol -s hybrid --rtd3 3 || die "envycontrol failed (see output above)."
    ok "EnvyControl set to hybrid (--rtd3 3)."
    relogin_note
    ;;
esac
