#!/bin/bash
# Classroom v2 test lab driver.
#
# The development host is a VM with no /dev/kvm, so the desktop under test
# runs inside a systemd container instead of a virtual machine. Nothing this
# script does touches the host outside Docker.
#
# The session is nested: an outer headless sway exists only to give the
# desktop under test a display that grim can capture and that sway's IPC can
# aim a real pointer at. The outer compositor is lab equipment, not part of
# the classroom design.
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
NAME="${LAB_NAME:-classroom-v2-lab}"
IMAGE="${LAB_IMAGE:-classroom-v2-lab:plasma}"
DOCKERFILE="${LAB_DOCKERFILE:-tools/lab/Dockerfile.plasma}"
SHOTS="${LAB_SHOTS:-$ROOT/docs/screenshots}"

OUTER=wayland-1

session_env() {
    docker exec -u classroom \
        -e XDG_RUNTIME_DIR=/run/user/1000 \
        -e HOME=/home/classroom \
        -e LANG=C.UTF-8 \
        -e DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
        "$@"
}

# Talk to the outer lab compositor: grim, swaymsg.
outer() {
    local sock
    sock=$(docker exec "$NAME" sh -c 'ls /run/user/1000/sway-ipc.* 2>/dev/null | head -1')
    session_env -e WAYLAND_DISPLAY="$OUTER" -e SWAYSOCK="$sock" "$NAME" "$@"
}

# Talk to the Plasma session under test.
inner() {
    session_env -e WAYLAND_DISPLAY=wayland-0 -e XDG_CURRENT_DESKTOP=KDE \
        -e QT_QPA_PLATFORM=wayland "$NAME" "$@"
}

case "${1:-}" in
build)
    shift
    exec docker build -f "$ROOT/$DOCKERFILE" -t "$IMAGE" "$@" "$ROOT"
    ;;

up)
    docker rm -f "$NAME" >/dev/null 2>&1 || true
    docker run -d --name "$NAME" \
        --privileged --cgroupns=private \
        --tmpfs /run --tmpfs /run/lock \
        --shm-size=1g \
        -v "$ROOT:/srv/classroom:ro" \
        "$IMAGE" >/dev/null
    for _ in $(seq 1 90); do
        state=$(docker exec "$NAME" systemctl is-system-running 2>/dev/null || true)
        [[ "$state" == running || "$state" == degraded ]] && break
        sleep 1
    done
    for _ in $(seq 1 30); do
        docker exec "$NAME" test -S /run/user/1000/bus && break
        sleep 1
    done
    # startplasma looks for `qdbus`; Debian ships it as qdbus6.
    docker exec "$NAME" ln -sf /usr/bin/qdbus6 /usr/local/bin/qdbus
    echo "lab $NAME is up ($(docker exec "$NAME" systemctl is-system-running 2>/dev/null))"
    ;;

down)
    docker rm -f "$NAME" >/dev/null 2>&1 || true
    echo "lab $NAME is down"
    ;;

outer-up)
    session_env \
        -e WLR_BACKENDS=headless -e WLR_LIBINPUT_NO_DEVICES=1 \
        -e WLR_RENDERER=pixman -e LIBGL_ALWAYS_SOFTWARE=1 \
        -d "$NAME" sh -c 'exec sway -c /srv/classroom/tools/lab/outer-sway.conf \
            > /tmp/outer-sway.log 2>&1'
    for _ in $(seq 1 30); do
        docker exec "$NAME" test -S "/run/user/1000/$OUTER" && break
        sleep 1
    done
    echo "outer compositor on $OUTER"
    ;;

plasma-up)
    session_env \
        -e WAYLAND_DISPLAY="$OUTER" -e XDG_SESSION_TYPE=wayland \
        -e XDG_CURRENT_DESKTOP=KDE -e LIBGL_ALWAYS_SOFTWARE=1 \
        -d "$NAME" sh -c 'exec startplasma-wayland > /tmp/plasma.log 2>&1'
    for _ in $(seq 1 60); do
        docker exec "$NAME" pgrep -x plasmashell >/dev/null 2>&1 && break
        sleep 1
    done
    sleep 5
    echo "plasma session up"
    ;;

plasma-down)
    docker exec "$NAME" pkill -u classroom -f startplasma-wayland || true
    docker exec "$NAME" pkill -u classroom -x plasmashell || true
    docker exec "$NAME" pkill -u classroom -x kwin_wayland || true
    sleep 2
    echo "plasma session down"
    ;;

session)
    "$0" outer-up
    "$0" plasma-up
    ;;

shot)
    # shot NAME [--delay SECONDS]
    name="${2:?usage: lab shot NAME}"
    outer grim /tmp/lab-shot.png >/dev/null
    mkdir -p "$SHOTS"
    docker exec "$NAME" cat /tmp/lab-shot.png > "$SHOTS/$name.png"
    echo "$SHOTS/$name.png"
    ;;

click)
    # click X Y   — a real pointer press in the session under test
    outer swaymsg seat - cursor set "$2" "$3" >/dev/null
    sleep 0.3
    outer swaymsg seat - cursor press button1 >/dev/null
    sleep 0.1
    outer swaymsg seat - cursor release button1 >/dev/null
    ;;

move)
    outer swaymsg seat - cursor set "$2" "$3" >/dev/null
    ;;

key)
    shift
    outer wtype "$@"
    ;;

sh)
    shift
    exec docker exec -it "$NAME" bash "$@"
    ;;

run)      shift; session_env "$NAME" "$@" ;;
irun)     shift; session_env -it "$NAME" "$@" ;;
inner)    shift; inner "$@" ;;
inner-it) shift; session_env -it -e WAYLAND_DISPLAY=wayland-0 -e XDG_CURRENT_DESKTOP=KDE "$NAME" "$@" ;;
outer)    shift; outer "$@" ;;

*)
    cat <<USAGE
usage: tools/lab/lab COMMAND

  build            build the lab image
  up               start the lab container (systemd inside)
  down             remove it
  session          outer compositor + a Plasma session on top of it
  outer-up         just the outer compositor
  plasma-up        just the Plasma session
  plasma-down      stop the Plasma session
  shot NAME        capture the screen to docs/screenshots/NAME.png
  click X Y        press the pointer at a screen position
  move X Y         move the pointer
  key ARGS...      wtype, aimed at the session
  inner CMD...     run CMD as a client of the Plasma session
  outer CMD...     run CMD against the lab compositor
  run CMD...       run CMD as the classroom user, no display
  sh               root shell in the lab
USAGE
    exit 1
    ;;
esac
