#!/bin/sh
# tisse-session — launch a full Tisse session (env + autostart + compositor)
#
# Usage:
#   ./scripts/tisse-session            # normal session
#   ./scripts/tisse-session -d         # debug session (logs to file)
#   ./scripts/tisse-session -s ""      # no autostart (bare compositor)
#
# Autostart (apps launched after WAYLAND_DISPLAY is live):
#   User:   ~/.config/tisse/autostart  (shell script, sourced)
#   System: /etc/tisse/autostart       (fallback)
#   Inline: swaybg + yambar            (fallback if no file found)
#
#   Copy scripts/autostart.example to ~/.config/tisse/autostart to
#   customise. Any valid shell syntax is accepted.
#
# Default keyboard: Swiss French (fr_CH).

set -eu

# ── Locate tisse binary ──────────────────────────────────────────────
# Installed (PATH): tisse-session lives in /usr/bin alongside tisse.
# Dev (repo):       script is scripts/tisse-session, binary is ../build/tisse.
if command -v tisse >/dev/null 2>&1; then
	BIN="tisse"
else
	ROOT="$(cd "$(dirname "$0")/.." && pwd)"
	BIN="$ROOT/build/tisse"
	if [ ! -x "$BIN" ]; then
		echo "tisse-session: tisse not found in PATH or $BIN" >&2
		echo "tisse-session: run 'meson setup build && ninja -C build' first." >&2
		exit 1
	fi
fi

# ── Refuse to run nested ─────────────────────────────────────────────
if [ -n "${WAYLAND_DISPLAY:-}" ] || [ -n "${DISPLAY:-}" ]; then
	echo "tisse: a graphical session is already active." >&2
	echo "tisse: this script is for TTY/DRM use. For nested mode use:" >&2
	echo "       ./scripts/run-nested.sh" >&2
	exit 1
fi

# ── Parse flags ──────────────────────────────────────────────────────
DEBUG=0
STARTUP_OVERRIDE=""      # set by -s; empty string = "no autostart"
STARTUP_OVERRIDE_SET=0   # distinguish -s "" from "not given"

while [ $# -gt 0 ]; do
	case "$1" in
		-d|--debug)
			DEBUG=1
			shift
			;;
		-s)
			STARTUP_OVERRIDE="${2:-}"
			STARTUP_OVERRIDE_SET=1
			shift 2
			;;
		-h|--help)
			sed -n '2,14p' "$0"
			exit 0
			;;
		*)
			echo "tisse: unknown flag: $1" >&2
			exit 1
			;;
	esac
done

# ── D-Bus session bus ────────────────────────────────────────────────
# Wrap the whole session in a private D-Bus session bus so notifications
# (fnott) and other dbus clients work. dbus-run-session starts the bus,
# exports DBUS_SESSION_BUS_ADDRESS to tisse and every child (the autostart
# included), and tears it down on exit. SliTaz ships it via the X-free
# `dbus-wayland` package. Skip if no bus tool, or if one is already set
# (e.g. launched from a session that already has dbus). The guard variable
# prevents re-entry after the re-exec.
if [ -z "${TISSE_DBUS_WRAPPED:-}" ] && [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ] \
		&& command -v dbus-run-session >/dev/null 2>&1; then
	export TISSE_DBUS_WRAPPED=1
	exec dbus-run-session -- "$0" "$@"
fi

# ── Resolve autostart command ────────────────────────────────────────
# Priority: -s flag > user config > system config > inline fallback.
# The command is passed to tisse -s and run via "sh -c CMD" after
# WAYLAND_DISPLAY is exported — all apps can connect immediately.
if [ $STARTUP_OVERRIDE_SET -eq 1 ]; then
	STARTUP_CMD="$STARTUP_OVERRIDE"
else
	USER_AUTOSTART="${XDG_CONFIG_HOME:-$HOME/.config}/tisse/autostart"
	SYS_AUTOSTART="/etc/tisse/autostart"

	if [ -f "$USER_AUTOSTART" ]; then
		STARTUP_CMD="sh \"$USER_AUTOSTART\""
		echo "tisse: autostart: $USER_AUTOSTART"
	elif [ -f "$SYS_AUTOSTART" ]; then
		STARTUP_CMD="sh \"$SYS_AUTOSTART\""
		echo "tisse: autostart: $SYS_AUTOSTART (system)"
	else
		# Inline fallback, resolved at runtime so a minimal base still
		# gets a wallpaper and panel with whatever is installed:
		#   - background: a "wallpaper = /path" set via tisse-config wins
		#     (wbg); else swaybg (solid colour); else wbg with the image
		#     shipped by the tisse package. If none is available the
		#     compositor's own solid fill (bg_color) shows through.
		#   - panel: yambar if present.
		STARTUP_CMD='
_wall=""
for _cfg in "${XDG_CONFIG_HOME:-$HOME/.config}/tisse/config" /etc/tisse/config; do
	[ -f "$_cfg" ] || continue
	_wall=$(sed -n "s/^[[:space:]]*wallpaper[[:space:]]*=[[:space:]]*//p" "$_cfg" | tail -1)
	[ -n "$_wall" ] && break
done
if [ -n "$_wall" ] && command -v wbg >/dev/null 2>&1; then
	wbg "$_wall" &
elif command -v swaybg >/dev/null 2>&1; then
	swaybg -c "#1e1e2e" &
elif command -v wbg >/dev/null 2>&1 && [ -f /usr/share/backgrounds/tisse.png ]; then
	wbg /usr/share/backgrounds/tisse.png &
fi
if command -v yambar >/dev/null 2>&1; then
	if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/yambar/config.yml" ]; then
		yambar &
	else
		yambar -c /etc/tisse/yambar-config.yml &
	fi
fi
'
		echo "tisse: autostart: inline fallback (copy scripts/autostart.example to $USER_AUTOSTART to customise)"
	fi
fi

# ── Keyboard: Swiss French ───────────────────────────────────────────
export XKB_DEFAULT_LAYOUT=ch
export XKB_DEFAULT_VARIANT=fr

# ── XDG runtime dir (required by Wayland) ────────────────────────────
if [ -z "${XDG_RUNTIME_DIR:-}" ]; then
	export XDG_RUNTIME_DIR="/run/user/$(id -u)"
	if [ ! -d "$XDG_RUNTIME_DIR" ]; then
		XDG_RUNTIME_DIR="/tmp/tisse-runtime-$(id -u)"
		export XDG_RUNTIME_DIR
		mkdir -p "$XDG_RUNTIME_DIR"
		chmod 700 "$XDG_RUNTIME_DIR"
		echo "tisse: created fallback XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR" >&2
	fi
fi

# ── Cursor theme ─────────────────────────────────────────────────────
export XCURSOR_SIZE=24
export XCURSOR_THEME=default

# ── Build tisse argument list ─────────────────────────────────────────
set -- "$BIN"
[ $DEBUG -eq 1 ] && set -- "$@" -d
[ -n "$STARTUP_CMD" ] && set -- "$@" -s "$STARTUP_CMD"

# ── Launch helpers ────────────────────────────────────────────────────
# stdbuf line-buffers tisse's output for a readable real-time log, but is
# absent from minimal bases (busybox) — use it only when present.
exec_tisse() {
	if command -v stdbuf >/dev/null 2>&1; then
		exec stdbuf -oL -eL "$@"
	else
		exec "$@"
	fi
}
run_tisse() {
	if command -v stdbuf >/dev/null 2>&1; then
		stdbuf -oL -eL "$@"
	else
		"$@"
	fi
}

# Launch tisse with a one-shot fallback to the Pixman software renderer.
# wlroots' default GLES2 renderer fails to initialise when the GPU has no
# usable GLES2/EGL stack (QEMU -vga std, VMs, or a live image shipping no
# Mesa DRI drivers); the failure is near-instant at startup. If tisse dies
# within a few seconds without having been asked to quit, retry once
# forcing pixman. A clean logout or a late crash (long uptime) is left
# alone, and a renderer pinned by the user is always respected.
launch() {
	# Renderer pinned (by the user or a previous fallback): exec straight
	# into tisse so SIGTERM/SIGINT reach it directly for clean teardown.
	if [ -n "${WLR_RENDERER:-}" ]; then
		exec_tisse "$@"
	fi

	# First attempt on the default renderer. We can't exec — the shell
	# must stay alive to detect a fast startup failure — so run tisse in
	# the background and forward teardown signals to it.
	got_signal=0
	trap 'got_signal=1; kill -TERM "$child" 2>/dev/null' TERM INT
	run_tisse "$@" &
	child=$!
	start=$(date +%s)
	wait "$child"
	rc=$?
	trap - TERM INT

	if [ $rc -ne 0 ] && [ $got_signal -eq 0 ] \
		&& [ $(( $(date +%s) - start )) -lt 5 ]; then
		echo "tisse: startup failed (exit $rc), retrying with WLR_RENDERER=pixman" >&2
		export WLR_RENDERER=pixman
		exec_tisse "$@"
	fi
	exit $rc
}

# ── Debug logging ────────────────────────────────────────────────────
if [ $DEBUG -eq 1 ]; then
	LOG_DIR="${ROOT:-$HOME/.local/share/tisse}/logs"
	mkdir -p "$LOG_DIR"
	TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
	LOG_FILE="$LOG_DIR/tisse-$TIMESTAMP.log"
	ln -sfn "tisse-$TIMESTAMP.log" "$LOG_DIR/tisse-latest.log"
	echo "tisse: debug mode → $LOG_FILE"
	launch "$@" >"$LOG_FILE" 2>&1
fi

# ── Normal mode ──────────────────────────────────────────────────────
launch "$@"
