#!/usr/bin/env bash
set -euo pipefail

ROOT=$(cd "$(dirname "$0")/.." && pwd)
LAB_HOST=${W3CS_LAB_HOST:?Set W3CS_LAB_HOST, for example ubuntu@203.0.113.10}
LAB_KEY=${W3CS_LAB_KEY:?Set W3CS_LAB_KEY to the SSH private-key path}
LAB_REPLAY=${W3CS_LAB_REPLAY:-/home/ubuntu/w3cs-lab/test.w3g}
REMOTE_ROOT=${W3CS_LAB_REMOTE_ROOT:-/home/ubuntu/w3cs-lab}
HTTP_PORT=${W3CS_LAB_HTTP_PORT:-8150}
BRIDGE_PORT=${W3CS_LAB_BRIDGE_PORT:-8145}
OPEN_BROWSER=${W3CS_LAB_OPEN_BROWSER:-1}
NO_RASTER=${W3CS_LAB_NO_RASTER:-1}
NATIVE_RELAY=${W3CS_LAB_NATIVE_RELAY:-1}
SOURCE_WIDTH=${W3CS_LAB_SOURCE_WIDTH:-1024}
SOURCE_HEIGHT=${W3CS_LAB_SOURCE_HEIGHT:-768}
CAPTURE_FPS=${W3CS_LAB_CAPTURE_FPS:-40}
GAME_FPS=${W3CS_LAB_GAME_FPS:-60}
PERSISTENT_SESSION=${W3CS_LAB_PERSISTENT_SESSION:-1}
WARM_REPLAY=${W3CS_LAB_WARM_REPLAY:-default}
WARM_PROFILE=${W3CS_LAB_WARM_PROFILE:-native-1285}
DEBUG=${W3CS_LAB_DEBUG:-0}
PROFILE_124AB_ARTIFACT=${W3CS_LAB_PROFILE_124AB_ARTIFACT:-}
PROFILE_124CDE_ARTIFACT=${W3CS_LAB_PROFILE_124CDE_ARTIFACT:-}
CATALOG_INDEX=${W3CS_LAB_CATALOG_INDEX:-}
CATALOG_BUCKET=${W3CS_LAB_CATALOG_BUCKET:-}
CATALOG_REGION=${W3CS_LAB_CATALOG_REGION:-us-east-1}
SSH=(ssh -o BatchMode=yes -i "$LAB_KEY")
SCP=(scp -o BatchMode=yes -i "$LAB_KEY")

local_pids=()
cleanup() {
  for pid in "${local_pids[@]-}"; do
    kill "$pid" 2>/dev/null || true
  done
}
trap cleanup EXIT INT TERM

make -C "$ROOT/native" d3d9.dll
"${SCP[@]}" \
  "$ROOT/lab_live_bridge.py" "$ROOT/relay.py" "$ROOT/protocol.py" \
  "$ROOT/native/d3d9.dll" \
  "$ROOT/native/w3cs_webrtc_relay.cpp" "$ROOT/native/w3cs_protocol.h" \
  "$ROOT/native/lab-live.sh" "$ROOT/native/lab-game-session.sh" \
  "$ROOT/native/lab-switch-replay.sh" \
  "$ROOT/native/stage-replay-session.py" \
  "$ROOT/native/materialize-catalog-replay.py" \
  "$ROOT/native/lab-install-engine-profiles.sh" \
  "$LAB_HOST:$REMOTE_ROOT/"
if [[ -n "$PROFILE_124AB_ARTIFACT" ]]; then
  "${SCP[@]}" "$PROFILE_124AB_ARTIFACT" \
    "$LAB_HOST:$REMOTE_ROOT/wc3-classic-124ab-runtime-proof-v1.tgz"
fi
if [[ -n "$PROFILE_124CDE_ARTIFACT" ]]; then
  "${SCP[@]}" "$PROFILE_124CDE_ARTIFACT" \
    "$LAB_HOST:$REMOTE_ROOT/wc3-classic-124cde-runtime-proof-v1.tgz"
fi
if [[ -n "$CATALOG_INDEX" ]]; then
  [[ -f "$CATALOG_INDEX" ]] || {
    printf 'Catalog index does not exist: %s\n' "$CATALOG_INDEX" >&2
    exit 2
  }
  [[ -n "$CATALOG_BUCKET" ]] || {
    printf 'W3CS_LAB_CATALOG_BUCKET is required with a catalog index\n' >&2
    exit 2
  }
  "${SCP[@]}" "$CATALOG_INDEX" \
    "$LAB_HOST:$REMOTE_ROOT/catalog-index.json"
fi

# ssh flattens its arguments into one command line, so an empty value (for
# example no catalog bucket) would vanish and shift every later positional.
# printf %q keeps empty and special arguments intact.
remote_args=$(printf '%q ' \
  "$REMOTE_ROOT" "$LAB_REPLAY" "$NO_RASTER" \
  "$SOURCE_WIDTH" "$SOURCE_HEIGHT" "$NATIVE_RELAY" "$CAPTURE_FPS" \
  "$CATALOG_BUCKET" "$CATALOG_REGION" "$PERSISTENT_SESSION" \
  "$WARM_REPLAY" "$WARM_PROFILE" "$DEBUG" "$GAME_FPS")
"${SSH[@]}" "$LAB_HOST" bash -s -- $remote_args <<'REMOTE'
set -euo pipefail
remote_root=$1
replay=$2
no_raster=$3
source_width=$4
source_height=$5
native_relay=$6
capture_fps=$7
catalog_bucket=$8
catalog_region=$9
shift 9
persistent_session=$1
warm_replay=$2
warm_profile=$3
debug=$4
game_fps=$5
pid_file=/tmp/w3cs-e2e-parent.pid
chmod +x "$remote_root/lab-live.sh" "$remote_root/lab-game-session.sh" \
  "$remote_root/lab-switch-replay.sh"
chmod +x "$remote_root/lab-install-engine-profiles.sh"
if [[ -f "$remote_root/wc3-classic-124ab-runtime-proof-v1.tgz" && \
      -f "$remote_root/wc3-classic-124cde-runtime-proof-v1.tgz" ]]; then
  "$remote_root/lab-install-engine-profiles.sh"
fi
if [[ "$native_relay" == 1 ]]; then
  g++ -O3 -g0 -std=c++20 -Wall -Wextra -Werror -pthread \
    -DGST_USE_UNSTABLE_API "$remote_root/w3cs_webrtc_relay.cpp" \
    -o "$remote_root/w3cs-webrtc-relay" \
    $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-webrtc-1.0 \
      gstreamer-sdp-1.0 libsoup-3.0 json-glib-1.0 x11 xfixes xtst zlib \
      libzstd)
fi
if [[ -r "$pid_file" ]]; then
  old_pid=$(tr -cd '0-9' <"$pid_file")
  if [[ -n "$old_pid" ]] && kill -0 "$old_pid" 2>/dev/null; then
    kill "$old_pid"
    for _ in $(seq 1 30); do
      kill -0 "$old_pid" 2>/dev/null || break
      sleep .1
    done
  fi
fi
: >/tmp/w3cs-bridge.log
wine_debug=-all
if [[ "$debug" == 1 ]]; then
  wine_debug=+debugstr
fi
nohup env W3_D3D9_TEST_REPLAY="$replay" W3_D3D9_NO_RASTER="$no_raster" \
  W3_D3D9_DEBUG="$debug" \
  WINEDEBUG="$wine_debug" \
  W3CS_NATIVE_RELAY="$native_relay" \
  W3_D3D9_SOURCE_WIDTH="$source_width" \
  W3_D3D9_SOURCE_HEIGHT="$source_height" \
  W3_D3D9_CAPTURE_FPS="$capture_fps" \
  W3_D3D9_MAX_FPS="$game_fps" \
  W3CS_CATALOG_INDEX="$remote_root/catalog-index.json" \
  W3CS_CATALOG_BUCKET="$catalog_bucket" \
  W3CS_CATALOG_REGION="$catalog_region" \
  W3CS_PERSISTENT_SESSION="$persistent_session" \
  W3CS_WARM_REPLAY="$warm_replay" \
  W3CS_WARM_PROFILE="$warm_profile" \
  "$remote_root/lab-live.sh" >/tmp/w3cs-parent.log 2>&1 </dev/null &
echo $! >"$pid_file"
parent_pid=$!
for _ in $(seq 1 80); do
  if grep -q 'listening' /tmp/w3cs-bridge.log 2>/dev/null; then
    exit 0
  fi
  if ! kill -0 "$parent_pid" 2>/dev/null; then
    tail -n 80 /tmp/w3cs-parent.log /tmp/w3cs-bridge.log 2>/dev/null || true
    exit 1
  fi
  sleep .25
done
tail -n 80 /tmp/w3cs-parent.log /tmp/w3cs-bridge.log 2>/dev/null || true
exit 1
REMOTE

python3 "$ROOT/poc/no_store_http.py" --port "$HTTP_PORT" \
  --bind 127.0.0.1 --directory "$ROOT" \
  >/tmp/w3cs-e2e-http.log 2>&1 &
local_pids+=("$!")
for _ in $(seq 1 40); do
  curl --fail --silent "http://127.0.0.1:$HTTP_PORT/README.md" \
    >/dev/null 2>&1 && break
  kill -0 "${local_pids[0]}" 2>/dev/null || {
    cat /tmp/w3cs-e2e-http.log >&2
    exit 1
  }
  sleep .05
done
curl --fail --silent "http://127.0.0.1:$HTTP_PORT/README.md" \
  >/dev/null

"${SSH[@]}" -o ExitOnForwardFailure=yes -o ServerAliveInterval=10 \
  -o ServerAliveCountMax=3 -N \
  -L "127.0.0.1:$BRIDGE_PORT:127.0.0.1:8145" "$LAB_HOST" &
local_pids+=("$!")

for _ in $(seq 1 80); do
  if python3 - "$BRIDGE_PORT" >/dev/null 2>&1 <<'PY'
import socket
import sys
with socket.create_connection(("127.0.0.1", int(sys.argv[1])), .1):
    pass
PY
  then
    break
  fi
  kill -0 "${local_pids[1]}" 2>/dev/null || exit 1
  sleep .05
done
python3 - "$BRIDGE_PORT" <<'PY'
import socket
import sys
with socket.create_connection(("127.0.0.1", int(sys.argv[1])), .5):
    pass
PY

build_id=$(python3 - "$ROOT/poc/interactive-live.html" <<'PY'
from pathlib import Path
import hashlib
import sys
print(hashlib.sha256(Path(sys.argv[1]).read_bytes()).hexdigest()[:12])
PY
)
transport=ws
if [[ "$NATIVE_RELAY" == 1 ]]; then
  transport=webrtc
fi
url="http://127.0.0.1:$HTTP_PORT/poc/interactive-live.html?bridgePort=$BRIDGE_PORT&transport=$transport&build=$build_id&profile=$WARM_PROFILE"
printf 'WC3 client-GPU lab: %s\n' "$url"
if [[ "$OPEN_BROWSER" == 1 ]] && command -v open >/dev/null 2>&1; then
  open "$url"
fi
wait "${local_pids[@]}"
