#!/bin/bash
# Builds a real GVFS mount to test the NETWORK rail against, at zero privilege. Self-documenting below.
set -u
# Hard rule 9's guard owns FIXTURE_ROOT and every absolute, root and containment check below, and
# sandbox_remove's own marker is what stands between this directory and rm -rf. Unlike the media and
# matched fixtures this one never deletes anything itself, so it carries no second marker of its own.
. "$(dirname "$0")/../tools/flea-sandbox-guard"

# A zip mounted through gvfsd-archive is a genuine GVFS mount: it lists in "gio mount -l" as a real
# Mount() line, "gio info" answers a real "local path:" under /run/user/<uid>/gvfs, and "gio mount -u"
# releases it. So ui/NetworkMounts.qml cannot tell it from a share, which is what makes the whole
# NETWORK group drivable with no privilege, no credential prompt, no network and no real NAS.
# It replaces the old belief that mount refresh could only be tested against the operator's own box.
#
#   tools/flea-gvfs-fixture make            builds the zip and prints its archive uri
#   tools/flea-gvfs-fixture mount           mounts it
#   tools/flea-gvfs-fixture uri             prints the uri without building
#   tools/flea-gvfs-fixture unmount         releases it
#   tools/flea-gvfs-fixture clean           releases it and removes the sandbox
#
# A bookmarks line for it, which is what puts an unmounted row on the rail to activate:
#   printf '%s FixShare\n' "$(tools/flea-gvfs-fixture uri)" > "$HOME/.config/gtk-3.0/bookmarks"
#
# To drive the wedge that ui/MountListing.qml's timeoutMs exists for, put a gio on PATH ahead of
# the real one that sleeps on "mount -li" and execs /usr/bin/gio for everything else. The same shape
# with lsblk drives ui/DeviceMounts.qml. A stub that cannot hang cannot catch a hang, which is why
# tests/ui.sh case_sharebrowser, whose stub prints nothing for "mount -li", never caught either.

dir=${DIR:-$FIXTURE_ROOT/flea-gvfs-fixture}
# gio reports the archive host double-encoded, and only that form round trips through mount and
# unmount, so the uri is built the way gio prints it rather than the way it is first accepted.
zip_name=share.zip

fail() {
    printf 'flea-gvfs-fixture: %s\n' "$*" >&2
    exit 1
}

command -v zip >/dev/null || fail "no zip on PATH"
command -v gio >/dev/null || fail "no gio on PATH"

uri_for() {
    python3 - "$1" <<'PY'
import sys, urllib.parse
inner = "file://" + sys.argv[1]
print("archive://" + urllib.parse.quote(urllib.parse.quote(inner, safe=""), safe="") + "/")
PY
}

archive="$dir/$zip_name"

make_fixture() {
    sandbox_make "$dir"
    mkdir -p "$dir/src"
    printf 'alpha\n' > "$dir/src/alpha.txt"
    printf 'beta\n' > "$dir/src/beta.txt"
    ( cd "$dir/src" && zip -q "$archive" alpha.txt beta.txt ) || fail "could not build $archive"
    uri_for "$archive"
}

live_uri() {
    gio mount -l 2>/dev/null | sed -n 's/^Mount([0-9]*): [^>]*-> //p' | grep -F "$zip_name" | head -1
}

case "${1:-make}" in
    make)
        make_fixture
        ;;
    uri)
        [ -f "$archive" ] || fail "no fixture at $archive, run make first"
        uri_for "$archive"
        ;;
    mount)
        [ -f "$archive" ] || fail "no fixture at $archive, run make first"
        gio mount "$(uri_for "$archive")" || fail "could not mount the fixture"
        ;;
    unmount)
        u=$(live_uri)
        # Nothing mounted is a success: this is what every test's exit path calls.
        [ -n "$u" ] || exit 0
        gio mount -u "$u" || fail "could not unmount $u"
        ;;
    clean)
        u=$(live_uri)
        [ -n "$u" ] && gio mount -u "$u" >/dev/null 2>&1
        sandbox_remove "$dir"
        ;;
    *)
        fail "unknown action '$1', expected make, uri, mount, unmount or clean"
        ;;
esac
