#!/usr/bin/env bash

# Workspaces on the primary display only.
#
# monitors.lua turns one preference into workspace rules, and the rules are the
# part that cannot be taken back: Hyprland reads them at config time and offers
# no way to remove one afterwards -- an empty monitor leaves the old binding in
# place, which was checked rather than assumed. Only a reload clears them, so
# what this file emits IS the state of the desktop, and emitting one rule too
# many strands a workspace on a screen until the next reload.
#
# The Lua is exercised with a stubbed `hl`, so the rules can be counted without
# a compositor and without touching the running desktop.

set -uo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
hypr_dir="$repo_dir/config/dot/hypr"
schema="$repo_dir/config/dot/quickshell/config/PreferenceSchema.qml"
page="$repo_dir/config/dot/quickshell/modules/settings/DisplaysPage.qml"
service="$repo_dir/config/dot/quickshell/services/Workspaces.qml"
keybinds="$hypr_dir/keybinds.lua"

findings=()
note() { findings+=("$1"); }

command -v lua >/dev/null 2>&1 || {
    printf 'workspace rules contract: lua is not installed\n' >&2
    exit 1
}

work="$(mktemp -d /tmp/panama-workspace-rules.XXXXXX)"
trap 'rm -rf "$work"' EXIT
mkdir -p "$work/config/panama"

# Every workspace rule monitors.lua emits for a given settings file, as
# "workspace monitor" lines. hl.monitor is swallowed: this is about workspaces,
# and a monitor call is not one.
emit() {
    printf '%s' "$1" >"$work/config/panama/settings.json"
    XDG_CONFIG_HOME="$work/config" lua -e "
        package.path = '$hypr_dir/?.lua;' .. package.path
        hl = {
            monitor = function() end,
            workspace_rule = function(rule)
                print(tostring(rule.workspace) .. ' ' .. tostring(rule.monitor))
            end,
        }
        dofile('$hypr_dir/monitors.lua')
    " 2>/dev/null
}

PRIMARY='{"displays":{"DP-2":{"mode":"4500x3000@60","scale":1.5,"transform":0,"x":0,"y":0,"primary":true}}'

# ── Off: Hyprland's own behaviour, which needs no rules at all ────────────────

off="$(emit "$PRIMARY,\"workspacesOnPrimaryOnly\":false}")"
[[ -z "$off" ]] || note "with the setting off, $(wc -l <<<"$off") workspace rules are still emitted"

absent="$(emit "$PRIMARY}")"
[[ -z "$absent" ]] || note 'with the setting absent, workspace rules are emitted anyway'

# ── On: every workspace the keybinds reach, and no more ──────────────────────

on="$(emit "$PRIMARY,\"workspacesOnPrimaryOnly\":true}")"
emitted="$(grep -c . <<<"$on" || true)"

# The count is not a magic number: it is how many workspaces ALT+1..ALT+0 reach.
# If keybinds.lua ever binds a different number, pinning the old count leaves
# some workspaces pinned and others not, which is worse than either.
bound="$(sed -n 's/.*for i = 1, \([0-9]*\) do.*/\1/p' "$keybinds" | head -1)"
[[ -n "$bound" ]] || bound=10

(( emitted == bound )) \
    || note "the setting pins $emitted workspaces but the keybinds reach $bound"

while read -r workspace monitor; do
    [[ -n "$workspace" ]] || continue
    [[ "$monitor" == "DP-2" ]] \
        || note "workspace $workspace is pinned to '$monitor' rather than the primary display"
done <<<"$on"

# ── On, with nothing to pin to ───────────────────────────────────────────────
#
# A machine can have the preference set and no primary recorded -- it is the
# state this one is in. Guessing a primary would move every workspace onto
# whichever output happened to sort first.

no_primary="$(emit '{"workspacesOnPrimaryOnly":true}')"
[[ -z "$no_primary" ]] \
    || note 'with no primary display recorded, workspaces are pinned to a guess'

# ── The preference cannot pretend to be an option ────────────────────────────

if grep -q 'key: "workspacesOnPrimaryOnly"' "$schema"; then
    block="$(sed -n '/key: "workspacesOnPrimaryOnly"/,/^        },/p' "$schema")"
    grep -q 'hypr:' <<<"$block" \
        && note 'workspacesOnPrimaryOnly declares a hypr option, but workspace rules are not settable options'
else
    note 'workspacesOnPrimaryOnly is not in the schema'
fi

# ── The page tells the truth ─────────────────────────────────────────────────

grep -q 'Displays.monitors.length >= 2' "$page" \
    || note 'the Workspaces card is not hidden on a single-display machine'

# Applied has to be read back from the compositor. Inferring it from the
# preference having been written is how a page comes to claim a setting is in
# effect when it is waiting on a reload.
grep -q 'hyprctl", "-j", "workspacerules' "$service" \
    || note 'the service never reads the compositor, so it cannot know whether the setting took effect'
grep -q '"hyprctl", "reload"' "$service" \
    || note 'the service has no way to apply the setting'

# ── Report ───────────────────────────────────────────────────────────────────

if (( ${#findings[@]} > 0 )); then
    mapfile -t findings < <(printf '%s\n' "${findings[@]}" | sort -u)
    printf 'workspace rules contract: %d finding(s)\n' "${#findings[@]}" >&2
    printf '  - %s\n' "${findings[@]}" >&2
    exit 1
fi

printf 'workspace rules contract: PASS (%d workspaces pinned when enabled)\n' "$emitted"
