#!/usr/bin/env bash
# M6 text-input test under quibble:
#   1. click focuses the first field; typed text lands in it,
#   2. select-all + typing replaces,
#   3. Tab moves focus (screenshots differ: focus ring moves),
#   4. clipboard round-trips through the compositor both directions,
#   5. idle renders only the caret-blink cadence.
set -euo pipefail
cd "$(dirname "$0")/.."

cargo build -p guiduck --example m6_form
cargo build -p guiduck-render-tinyskia --bin png-diff

workdir=$(mktemp -d)
sock="$workdir/quibble.sock"
cleanup() {
    quibblectl --socket "$sock" quit >/dev/null 2>&1 || true
    rm -rf "$workdir"
}
trap cleanup EXIT

# Layout at 480x360: title at y16..~40, first field y~52 h~32, second y~96,
# button y~140. Click points centered in each.
FIRST_X=130;  FIRST_Y=68
BUTTON_X=76;  BUTTON_Y=158
# evdev keycodes
KEY_TAB=15; KEY_LEFTCTRL=29; KEY_A=30; KEY_C=46; KEY_V=47

GUIDUCK_BACKEND=software GUIDUCK_TRACE_FRAMES=1 \
    quibble --socket "$sock" --width 480 --height 360 \
    target/debug/examples/m6_form \
    >"$workdir/out.log" 2>"$workdir/err.log" &
for _ in $(seq 1 50); do
    quibblectl --socket "$sock" ping >/dev/null 2>&1 && break
    sleep 0.2
done
quibblectl --socket "$sock" wait-window --timeout-ms 30000 >/dev/null
sleep 1

frames() { grep -c '^guiduck-frame' "$workdir/err.log" || true; }
combo() { # ctrl+<key>
    quibblectl --socket "$sock" key $KEY_LEFTCTRL press >/dev/null
    quibblectl --socket "$sock" key "$1" press >/dev/null
    quibblectl --socket "$sock" key "$1" release >/dev/null
    quibblectl --socket "$sock" key $KEY_LEFTCTRL release >/dev/null
}
print_values() {
    quibblectl --socket "$sock" pointer-move $BUTTON_X $BUTTON_Y >/dev/null
    quibblectl --socket "$sock" click >/dev/null
    sleep 0.4
    grep '^first=' "$workdir/out.log" | tail -1
}
fail=0

# 1: click into the first field and type.
quibblectl --socket "$sock" pointer-move $FIRST_X $FIRST_Y >/dev/null
quibblectl --socket "$sock" click >/dev/null
sleep 0.3
quibblectl --socket "$sock" type "hello world" >/dev/null
sleep 0.4
v=$(print_values)
if [ "$v" = "first=hello world second=prefilled" ]; then
    echo "typing: ok ($v)"
else
    echo "FAIL: typing; got '$v'" >&2; fail=1
fi

# 2: select-all + typing replaces (click back into the first field first).
quibblectl --socket "$sock" pointer-move $FIRST_X $FIRST_Y >/dev/null
quibblectl --socket "$sock" click >/dev/null
combo $KEY_A
quibblectl --socket "$sock" type "replaced" >/dev/null
sleep 0.4
v=$(print_values)
if [ "$v" = "first=replaced second=prefilled" ]; then
    echo "select-all replace: ok"
else
    echo "FAIL: replace; got '$v'" >&2; fail=1
fi

# 3: Tab moves focus; the focus ring moves (pixels differ).
quibblectl --socket "$sock" pointer-move $FIRST_X $FIRST_Y >/dev/null
quibblectl --socket "$sock" click >/dev/null
sleep 0.3
quibblectl --socket "$sock" screenshot -o "$workdir/focus1.png" >/dev/null
quibblectl --socket "$sock" key $KEY_TAB press >/dev/null
quibblectl --socket "$sock" key $KEY_TAB release >/dev/null
sleep 0.4
quibblectl --socket "$sock" screenshot -o "$workdir/focus2.png" >/dev/null
if cmp -s "$workdir/focus1.png" "$workdir/focus2.png"; then
    echo "FAIL: Tab did not move the focus ring" >&2; fail=1
else
    echo "tab focus: ring moved"
fi

# 4: clipboard both directions through the compositor.
#    (a) app -> compositor: select-all + copy in field two, read via quibblectl.
combo $KEY_A
combo $KEY_C
sleep 0.4
clip=$(quibblectl --socket "$sock" clipboard-get 2>/dev/null || echo "<none>")
if [ "$clip" = "prefilled" ]; then
    echo "clipboard copy: compositor sees '$clip'"
else
    echo "FAIL: clipboard copy; compositor sees '$clip'" >&2; fail=1
fi
#    (b) compositor -> app: set clipboard, paste over field two.
quibblectl --socket "$sock" clipboard-set "from-outside" >/dev/null
combo $KEY_A
combo $KEY_V
sleep 0.4
v=$(print_values)
if [ "$v" = "first=replaced second=from-outside" ]; then
    echo "clipboard paste: ok"
else
    echo "FAIL: clipboard paste; got '$v'" >&2; fail=1
fi

# 5: idle with a focused text input = the caret blink cadence, and
# nothing more. ~5-6 toggles in 3s at the 530ms interval; a count outside
# [3, 9] means the blink stalled or something renders beyond it.
q0=$(frames); sleep 3; q1=$(frames)
d=$((q1 - q0))
echo "idle frames: $q0 -> $q1 (blink cadence: $d)"
{ [ "$d" -ge 3 ] && [ "$d" -le 9 ]; } || { echo "FAIL: expected caret-blink cadence while idle, got $d frames" >&2; fail=1; }

cp "$workdir/focus1.png" "$workdir/focus2.png" target/ 2>/dev/null || true
[ "$fail" -eq 0 ] && echo "M6 text-input test PASSED"
exit $fail
