#!/bin/bash
# How large is a lesson in Wonder Ink, and do the keys change it?
#
# Runs the INSTALLED classroom-wonderink under a real QtWebEngine
# (offscreen), builds its window the way main() does, and asks the page
# itself what it is rendering at. Keys are delivered through Qt's own key
# path to the focused page — the same shortcut map a keyboard reaches —
# because the lab's injected keyboard does not reach the nested session.
# A physical Ctrl+Plus is a hardware check.
#
#   tools/lab/wonderink-zoom-check
set -uo pipefail

NAME="${LAB_NAME:-classroom-v2-lab}"
COMMAND="${WONDERINK:-/usr/local/bin/classroom-wonderink}"

docker exec -i \
    -e QT_QPA_PLATFORM=offscreen \
    -e QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox --disable-gpu" \
    -e COMMAND="$COMMAND" \
    "$NAME" bash -c 'export XDG_RUNTIME_DIR=$(mktemp -d) HOME=$(mktemp -d); python3 -' <<'PY'
import importlib.util, os, sys
from importlib.machinery import SourceFileLoader

loader = SourceFileLoader("wonderink", os.environ["COMMAND"])
spec = importlib.util.spec_from_loader("wonderink", loader)
ink = importlib.util.module_from_spec(spec)
loader.exec_module(ink)

from PyQt6.QtCore import QEventLoop, Qt, QTimer
from PyQt6.QtTest import QTest
from PyQt6.QtWebEngineCore import QWebEngineProfile
from PyQt6.QtWidgets import QApplication

app = QApplication(sys.argv[:1])
passed = failed = 0


def check(label, condition, detail=""):
    global passed, failed
    if condition:
        print(f"  \033[32mPASS\033[0m  {label}")
        passed += 1
    else:
        print(f"  \033[31mFAIL\033[0m  {label}" + (f"  [{detail}]" if detail else ""))
        failed += 1


def wait(ms):
    loop = QEventLoop()
    QTimer.singleShot(ms, loop.quit)
    loop.exec()


def page_dpr(view):
    answer = []
    view.page().runJavaScript("window.devicePixelRatio", answer.append)
    for _ in range(50):
        if answer:
            return answer[0]
        wait(100)
    return None


PAGE = "data:text/html,<title>lesson</title><p>Noah built an ark.</p>"
KEY = {
    "Ctrl+=": (Qt.Key.Key_Equal, Qt.KeyboardModifier.ControlModifier),
    "Ctrl+Plus": (Qt.Key.Key_Plus, Qt.KeyboardModifier.ControlModifier | Qt.KeyboardModifier.ShiftModifier),
    "keypad Ctrl+Plus": (Qt.Key.Key_Plus, Qt.KeyboardModifier.ControlModifier | Qt.KeyboardModifier.KeypadModifier),
    "Ctrl+Minus": (Qt.Key.Key_Minus, Qt.KeyboardModifier.ControlModifier),
    "keypad Ctrl+Minus": (Qt.Key.Key_Minus, Qt.KeyboardModifier.ControlModifier | Qt.KeyboardModifier.KeypadModifier),
    "Ctrl+0": (Qt.Key.Key_0, Qt.KeyboardModifier.ControlModifier),
    "Ctrl+Shift+Tab": (Qt.Key.Key_Backtab, Qt.KeyboardModifier.ControlModifier | Qt.KeyboardModifier.ShiftModifier),
}


def press(window, name):
    target = QApplication.focusWidget() or window.current()
    QTest.keyClick(target, *KEY[name])
    wait(400)


def open_window(room_zoom):
    profile = QWebEngineProfile(f"zoomcheck{room_zoom}", app)
    window = ink.WonderInk(profile, room_zoom=room_zoom)
    window.resize(1280, 800)
    window.show()
    for _ in range(3):
        window.open_tab(PAGE)
    wait(2500)
    window.current().setFocus()
    wait(300)
    return window


def factors(window):
    return [round(window._tabs.widget(i).zoomFactor(), 3) for i in range(window._tabs.count())]


print("1. a room's normal size is the browser's")
for room in (1.0, 1.5, 2.0):
    ink.SETTINGS.unlink(missing_ok=True)
    window = open_window(room)
    check(f"UI_SCALE {room}: every tab starts at {room}", factors(window) == [room] * 3, factors(window))
    window.close()
    wait(300)

print()
print("2. the keys a teacher knows, at UI_SCALE 1.5")
ink.SETTINGS.unlink(missing_ok=True)
window = open_window(1.5)
for name, level in (("Ctrl+=", 1.1), ("Ctrl+Plus", 1.25), ("keypad Ctrl+Plus", 1.5),
                    ("Ctrl+Minus", 1.25), ("keypad Ctrl+Minus", 1.1), ("Ctrl+0", 1.0)):
    press(window, name)
    check(f"{name} makes it {round(level * 100)}% in every tab",
          window.level() == level and factors(window) == [round(1.5 * level, 3)] * 3,
          f"level={window.level()} factors={factors(window)}")

press(window, "Ctrl+Plus")
dpr = page_dpr(window.current())
check("and the page itself renders at it", dpr is not None and abs(dpr - 1.65) < 0.01, dpr)

print()
print("3. new tabs, and the next time Wonder Ink opens")
view = window.open_tab(PAGE)
wait(1500)
check("a new tab starts at the teacher's size", round(view.zoomFactor(), 3) == 1.65, view.zoomFactor())
check("the level is saved on its own", ink.SETTINGS.read_text().strip() == "LEVEL=1.1",
      ink.SETTINGS.read_text())
check("in its own file, not the web profile",
      "wonderink-shell" not in str(ink.SETTINGS) and ink.SETTINGS.name == "wonderink.conf")
index = window._tabs.currentIndex()
press(window, "Ctrl+Shift+Tab")
check("Ctrl+Shift+Tab still goes back a tab", window._tabs.currentIndex() == index - 1,
      f"{index} -> {window._tabs.currentIndex()}")
window.close()
wait(300)

window = open_window(2.0)
check("reopened in a room at 2.0, the teacher's 110% is kept",
      window.level() == 1.1 and factors(window) == [2.2] * 3, factors(window))
window.close()

ink.SETTINGS.write_text("LEVEL=banana\n")
check("a damaged setting is the normal size", ink.load_level() == 1.0)
ink.SETTINGS.write_text("LEVEL=40\n")
check("an absurd one too", ink.load_level() == 1.0)

window = open_window(3.0)
press(window, "keypad Ctrl+Plus"); press(window, "keypad Ctrl+Plus"); press(window, "keypad Ctrl+Plus")
check("a large room zoomed further never passes the engine's limit",
      max(factors(window)) <= 5.0, factors(window))
window.close()

print()
print(f"{passed} passed, {failed} failed")
sys.exit(1 if failed else 0)
PY
