#!/bin/sh

# Run a unit-test command on a private X display.  Keeping the dispatcher
# narrow makes tools/unit-xvfb a useful approval prefix without approving an
# arbitrary command hidden behind env(1).

set -eu

usage='usage: tools/unit-xvfb --display :N [--watcom ROOT] run|turbo|dos16-build|dos32-build|serial|debug [arguments ...]'

if [ "${1-}" != "--display" ] || [ "$#" -lt 3 ]; then
   echo "$usage" >&2
   exit 2
fi
test_display=$2
shift 2

if [ "${1-}" = "--watcom" ]; then
   if [ "$#" -lt 3 ]; then
      echo "$usage" >&2
      exit 2
   fi
   WATCOM=$2
   shift 2
   if [ ! -d "$WATCOM/binl" ]; then
      echo "tools/unit-xvfb: Watcom binl directory is missing: $WATCOM/binl" >&2
      exit 2
   fi
fi

case "$test_display" in
   :0|:0.0)
      echo "tools/unit-xvfb: refusing interactive X display: $test_display" >&2
      exit 2
      ;;
   :[0-9]*) ;;
   *)
      echo "tools/unit-xvfb: invalid X display: $test_display" >&2
      exit 2
      ;;
esac

DISPLAY=$test_display
PYTHONDONTWRITEBYTECODE=1
export DISPLAY PYTHONDONTWRITEBYTECODE

if ! command -v Xvfb >/dev/null 2>&1; then
   echo "tools/unit-xvfb: Xvfb is not installed" >&2
   exit 1
fi
if ! command -v xdpyinfo >/dev/null 2>&1; then
   echo "tools/unit-xvfb: xdpyinfo is not installed" >&2
   exit 1
fi

Xvfb "$test_display" -screen 0 1024x768x24 -nolisten tcp \
   >/dev/null 2>&1 &
xvfb_pid=$!
trap 'kill "$xvfb_pid" 2>/dev/null || true; wait "$xvfb_pid" 2>/dev/null || true' \
   EXIT HUP INT TERM

xvfb_attempt=0
while ! xdpyinfo -display "$test_display" >/dev/null 2>&1; do
   if ! kill -0 "$xvfb_pid" 2>/dev/null; then
      echo "tools/unit-xvfb: Xvfb failed to start on $test_display" >&2
      exit 1
   fi
   xvfb_attempt=$((xvfb_attempt + 1))
   if [ "$xvfb_attempt" -ge 50 ]; then
      echo "tools/unit-xvfb: timed out starting Xvfb on $test_display" >&2
      exit 1
   fi
   sleep 0.1
done

if [ -z "${WATCOM-}" ] && [ -d "${HOME}/watcom" ]; then
   WATCOM=${HOME}/watcom
fi
if [ -n "${WATCOM-}" ] && [ -d "${WATCOM}/binl" ]; then
   PATH=${WATCOM}/binl:$PATH
   export WATCOM PATH
fi

command_name=${1-}
if [ "$#" -gt 0 ]; then
   shift
fi

case "$command_name" in
   run)
      python3 unit/tools/run.py "$@"
      ;;
   turbo)
      python3 unit/tools/turbo.py "$@"
      ;;
   dos16-build)
      if [ "$#" -ne 1 ]; then
         echo "tools/unit-xvfb: dos16-build requires a build directory" >&2
         exit 2
      fi
      CC=wcl
      export CC
      cmake -S dos -B "$1" -G Ninja \
         -D CMAKE_SYSTEM_NAME=DOS \
         -D CMAKE_SYSTEM_PROCESSOR=I86 \
         -D CMAKE_BUILD_TYPE=Release \
         -D OPENDOORS_WARNINGS_AS_ERRORS=ON
      cmake --build "$1"
      ;;
   dos32-build)
      if [ "$#" -ne 1 ]; then
         echo "tools/unit-xvfb: dos32-build requires a build directory" >&2
         exit 2
      fi
      CC=wcl386
      export CC
      cmake -S dos -B "$1" -G Ninja \
         -D CMAKE_SYSTEM_NAME=DOS \
         -D CMAKE_SYSTEM_PROCESSOR=I386 \
         -D CMAKE_BUILD_TYPE=Release \
         -D OPENDOORS_WARNINGS_AS_ERRORS=ON
      cmake --build "$1"
      ;;
   serial)
      if [ "$#" -lt 2 ]; then
         echo "tools/unit-xvfb: serial requires controller arguments, DOSBox, and a DOS door executable" >&2
         exit 2
      fi
      python3 tests/acceptance/dos_serial_controller.py "$@"
      ;;
   debug)
      if [ "$#" -lt 1 ] || [ "${1##*/}" != "dosbox" ]; then
         echo "tools/unit-xvfb: debug requires a DOSBox executable" >&2
         exit 2
      fi
      "$@"
      ;;
   *)
      echo "$usage" >&2
      exit 2
      ;;
esac
