#!/bin/sh
# Control menu: ./cs            (pick a number)
# or directly:  ./cs status | map <name> | mode dm|gg | bots <n> | kills | say <text>
#               ./cs restart | stop | start | logs | console | apply | update
D=$(cd "$(dirname "$0")" && pwd)
cd "$D" || exit 1
[ -f .env ] || { echo "no .env yet: run ./setup.sh first"; exit 1; }
getenv() { sed -n "s/^$1=//p" .env | tr -d '\r'; }
setenv() { sed -i "s|^$1=.*|$1=$2|" .env; }
NAME=$(getenv CS_NAME); NAME=${NAME:-cs16}
PORT=$(getenv CS_PORT); PORT=${PORT:-27015}
C=hlds/cstrike

status() {
  st=$(docker inspect -f '{{.State.Status}}' "$NAME" 2>/dev/null || echo "not created")
  if [ "$st" = running ]; then
    if out=$(python3 tools/hlq.py info 127.0.0.1 "$PORT" 2>/dev/null); then echo "  ${out#A2S_INFO ok: }"
    else echo "  container running, server not answering yet (starting or changing map?)"; fi
    if [ -f $C/addons/amxmodx/configs/plugins-gungame.ini ]; then echo "  mode: GunGame"; else echo "  mode: deathmatch"; fi
  else
    echo "  server is $st  (start it: ./cs start)"
  fi
}
players() { ./rcon status | grep -a -E '^#|^map|^players' ; }
setmap() {
  m=$1
  if [ -z "$m" ]; then
    echo "Maps on this server:"
    ls $C/maps/*.bsp 2>/dev/null | sed 's|.*/||; s|\.bsp$||' | nl -w3 -s') ' | pr -3 -t -w 90
    printf 'map name or number: '; read -r m
    case "$m" in ''|*[!0-9]*) ;; *) m=$(ls $C/maps/*.bsp | sed 's|.*/||; s|\.bsp$||' | sed -n "${m}p") ;; esac
  fi
  [ -n "$m" ] || return
  [ -f "$C/maps/$m.bsp" ] || { echo "no map called '$m' in $C/maps"; return; }
  r=$(./rcon changelevel "$m"); case "$r" in "(no answer"*) echo "$r" ;; *) echo "changing to $m" ;; esac
}
setmode() {
  m=$1
  [ -n "$m" ] || { printf 'mode: dm = deathmatch, gg = GunGame: '; read -r m; }
  case "$m" in dm|gg) ./rcon esef_mode "$m" | grep -a esef_mode ;; *) echo "use dm or gg" ;; esac
}
setbots() {
  n=$1
  [ -n "$n" ] || { printf 'fill the server up to how many players with bots? (0 = no bots, now %s): ' "$(getenv CS_BOTS)"; read -r n; }
  case "$n" in ''|*[!0-9]*) echo "give a number"; return ;; esac
  setenv CS_BOTS "$n"   # remembered for restarts
  r=$(./rcon yb_quota "$n"); case "$r" in "(no answer"*) echo "saved in .env, applies when the server is back: $r" ;; *) echo "bots: up to $n players (saved in .env)" ;; esac
}

run() {
  case "$1" in
    status|1)  status; players ;;
    map|2)     shift; setmap "$1" ;;
    mode|3)    shift; setmode "$1" ;;
    bots|4)    shift; setbots "$1" ;;
    kills|5)   python3 kills ;;
    say|6)     shift; t="$*"; [ -n "$t" ] || { printf 'message: '; read -r t; }; [ -n "$t" ] && ./rcon say "$t" > /dev/null && echo sent ;;
    restart|7) docker restart "$NAME" > /dev/null && echo "restarted (back in ~10 s)" ;;
    stop|8)    docker compose stop && echo "stopped (./cs start to start again)" ;;
    start|9)   docker compose up -d ;;
    logs|10)   echo "live server output, Ctrl+C to leave"; docker logs -f --tail 30 "$NAME" 2>&1 | grep --line-buffered -v -E 'rcon_password|sv_password|Rcon:' ;;
    console|11) ./rcon ;;
    apply|12)  docker compose up -d && echo "applied .env (server restarted if anything changed)" ;;
    update|13) ./setup.sh --yes --update ;;
    *) echo "unknown: $1 (try ./cs with no arguments)"; return 1 ;;
  esac
}

if [ $# -gt 0 ]; then run "$@"; exit $?; fi

while true; do
  echo
  echo "== $(getenv CS_HOSTNAME) ==  (container $NAME, UDP $PORT)"
  status
  cat <<'EOF'

   1) who's playing          8) stop server
   2) change map             9) start server
   3) game mode (DM / GG)   10) live log
   4) bots                  11) console (type server commands)
   5) kill counter          12) apply .env changes
   6) message to players    13) update game + mods
   7) restart server         0) quit
EOF
  printf '> '; read -r c || break
  case "$c" in 0|q|quit|exit|'') break ;; esac
  run "$c"
done
