#!/usr/bin/env bash
# Start and stop the Moonlight streaming stack on demand.
#
# It is not left running because it costs ~220 MiB of VRAM on the 3060 (sway
# ~112, Sunshine ~108) and that card also holds the local LLM. With an 11.3 GB
# model resident on a 12 GB card, 220 MiB is roughly a fifth of the remaining
# headroom — enough to matter for KV cache growth.
set -euo pipefail

UNIT=sway-headless.service
IDLE_MINUTES="${STREAM_IDLE_MINUTES:-15}"
STAMP="${XDG_RUNTIME_DIR:-/tmp}/stream.lastseen"

# A Moonlight client holds connections to the control and RTSP ports.
clients_connected() {
  ss -Htn state established '( sport = :47984 or sport = :47989 or sport = :48010 )' 2>/dev/null | grep -q .
}

vram() {
  local used total
  read -r used total < <(nvidia-smi --query-gpu=memory.used,memory.total \
    --format=csv,noheader,nounits 2>/dev/null | tr -d ',')
  printf '%s MiB used of %s, %s free' "$used" "$total" "$((total - used))"
}

case "${1:-status}" in
  on|start)
    systemctl --user start "$UNIT"
    sleep 6
    date +%s > "$STAMP"
    printf 'streaming up — pair or connect at https://%s:47990\n' "$(uname -n)"
    printf 'GPU: %s\n' "$(vram)"
    ;;
  off|stop)
    systemctl --user stop "$UNIT"
    sleep 3
    rm -f "$STAMP"
    printf 'streaming down\nGPU: %s\n' "$(vram)"
    ;;
  status)
    printf 'compositor: %s\nsunshine:   %s\nclients:    %s\nGPU:        %s\n' \
      "$(systemctl --user is-active "$UNIT")" \
      "$(systemctl --user is-active sunshine.service)" \
      "$(clients_connected && echo connected || echo none)" \
      "$(vram)"
    ;;
  --idle-check)
    # Called from sunshine-idle-stop.timer. Releases the GPU when nobody has
    # been connected for IDLE_MINUTES, so a forgotten session does not sit on
    # VRAM the inference stack wants.
    systemctl --user is-active --quiet "$UNIT" || exit 0
    if clients_connected; then date +%s > "$STAMP"; exit 0; fi
    last=$(cat "$STAMP" 2>/dev/null || echo 0)
    if (( last == 0 )); then date +%s > "$STAMP"; exit 0; fi
    if (( ($(date +%s) - last) >= IDLE_MINUTES * 60 )); then
      echo "no Moonlight client for ${IDLE_MINUTES}m; stopping to free the GPU"
      systemctl --user stop "$UNIT"
      rm -f "$STAMP"
    fi
    ;;
  *)
    echo "usage: stream [on|off|status]" >&2; exit 2 ;;
esac
