#!/bin/sh
# redrtos-appli — basculer une application RedRTOS entre RESIDENTE et A FROID.
#
#   redrtos-appli etat                                 qui est resident, qui tourne
#   redrtos-appli resident io.redsolution.redgallery
#   redrtos-appli froid    redgallery                  (nom court accepte)
#   redrtos-appli appliquer                            relit le fichier et synchronise
#
# ☠️ NE PAS PREFIXER PAR `sudo`. Le script demande lui-meme le mot de passe pour
#    la seule ecriture de /etc, et doit rester dans TA session pour le reste.
#    Jusqu'au 07/08 ces trois lignes montraient `sudo` : sous sudo, `id -u` vaut
#    0, XDG_RUNTIME_DIR pointe /run/user/0 qui n'existe pas, et le demarrage
#    echoue sur « Failed to connect to user scope bus ». Le reglage etait alors
#    ecrit SANS etre applique — le mode d'emploi cassait sa propre conception.
#
# ⚠️ Le reglage vit dans /etc/redrtos-applis.conf, donc dans le PAQUET, donc il
#    survit a une mise a jour. Ce qui vit dans ~/.config est perdu au reflashage :
#    c'est le defaut n°1 du projet, on ne le reproduit pas ici.
set -u

CONF=/etc/redrtos-applis.conf
APPLICATIONS=/usr/share/applications

# ☠️ Filet : lance sous sudo, ce script ecrirait le reglage puis echouerait a
#    l'appliquer, root n'ayant pas de bus de session. On refuse tot et on dit
#    quoi taper, plutot que de laisser croire que la bascule a eu lieu.
if [ "$(id -u)" = 0 ] && [ -n "${SUDO_USER:-}" ]; then
	echo "Ne lance pas redrtos-appli sous sudo." >&2
	echo "Root n'a pas de bus de session : le reglage serait ecrit mais JAMAIS" >&2
	echo "applique, et l'application resterait a froid sans que rien ne le dise." >&2
	echo "Tape simplement :  redrtos-appli $*" >&2
	echo "Le mot de passe te sera demande pour la seule ecriture de $CONF." >&2
	exit 2
fi

[ -n "${XDG_RUNTIME_DIR:-}" ] || XDG_RUNTIME_DIR="/run/user/$(id -u)"
export XDG_RUNTIME_DIR

usage() {
	sed -n '2,9p' "$0" | sed 's/^# \{0,1\}//'
	exit 2
}

# Traduit un nom court (« redgallery ») en identifiant complet
# (« io.redsolution.redgallery ») en cherchant dans le fichier de configuration.
# ⚠️ On cherche dans le FICHIER et pas dans /usr/share/applications : seules les
#    applications declarees ici ont une unite resident, et une correspondance
#    trouvee ailleurs donnerait une unite qui echoue.
resoudre() {
	_n=$1
	# Deja un identifiant complet present dans le fichier ?
	if grep -qE "^[[:space:]]*${_n}[[:space:]]" "$CONF" 2>/dev/null; then
		printf '%s' "$_n"
		return 0
	fi
	_trouve=$(awk -v n="$_n" '
		{ sub(/#.*/, ""); }
		NF >= 2 {
			id = $1
			nb = split(id, morceaux, ".")
			if (tolower(morceaux[nb]) == tolower(n)) print id
		}' "$CONF")
	_nb=$(printf '%s' "$_trouve" | grep -c . )
	if [ "$_nb" -eq 1 ]; then
		printf '%s' "$_trouve"
		return 0
	fi
	if [ "$_nb" -gt 1 ]; then
		echo "« $_n » est ambigu :" >&2
		printf '%s\n' "$_trouve" >&2
		return 1
	fi
	echo "« $_n » n'est pas dans $CONF." >&2
	echo "Applications connues :" >&2
	awk '{ sub(/#.*/, "") } NF >= 2 { print "  " $1 }' "$CONF" >&2
	return 1
}

# Ecrit le mode dans le fichier. Passe par sudo si on n'est pas root, MAIS
# seulement pour cette ecriture : les `systemctl --user` qui suivent doivent
# rester dans la session du proprietaire, pas dans celle de root (root n'a pas
# de bus de session ici, et l'application doit s'afficher sur SON ecran).
ecrire_mode() {
	_id=$1
	_mode=$2
	_tmp=$(mktemp) || return 1
	awk -v id="$_id" -v mode="$_mode" '
		{
			ligne = $0
			nu = ligne; sub(/#.*/, "", nu)
			n = split(nu, champs, /[ \t]+/)
			trouve = 0
			for (i = 1; i <= n; i++) if (champs[i] == id) trouve = 1
			if (trouve && n >= 2) { printf "%-30s %s\n", id, mode; vu = 1 }
			else print ligne
		}
		END { if (!vu) printf "%-30s %s\n", id, mode }
	' "$CONF" >"$_tmp" || { rm -f "$_tmp"; return 1; }

	# Filet : une erreur d'awk qui produirait un fichier vide effacerait toute
	# la configuration. On refuse d'ecrire un fichier plus court que 5 lignes.
	if [ "$(wc -l <"$_tmp")" -lt 5 ]; then
		echo "REFUS : le fichier reecrit est suspicieusement court. Rien n'a ete change." >&2
		rm -f "$_tmp"
		return 1
	fi

	if [ -w "$CONF" ]; then
		cat "$_tmp" >"$CONF"
	else
		sudo cp "$_tmp" "$CONF" || { rm -f "$_tmp"; return 1; }
		sudo chmod 644 "$CONF"
	fi
	rm -f "$_tmp"
}

etat() {
	printf '%-32s %-10s %-14s %s\n' "APPLICATION" "REGLAGE" "UNITE" "NOM D-BUS DETENU"
	awk '{ sub(/#.*/, "") } NF >= 2 { print $1, $2 }' "$CONF" | while read -r id mode; do
		unite=$(systemctl --user is-active "redrtos-appli@${id}.service" 2>/dev/null || true)
		[ -n "$unite" ] || unite="?"
		# ⚠️ `busctl --acquired` liste les noms BIEN CONNUS. Un `grep` sur la
		#    sortie complete de `busctl list` matcherait la colonne « user »
		#    et repondrait « oui » pour tout le monde.
		if busctl --user list --acquired --no-pager --no-legend 2>/dev/null \
			| awk '{ print $1 }' | grep -qx "$id"; then
			bus="oui"
		else
			bus="non"
		fi
		printf '%-32s %-10s %-14s %s\n' "$id" "$mode" "$unite" "$bus"
	done
	echo
	echo "Reglage  : ce que dit $CONF."
	echo "Unite    : ce que systemd fait REELLEMENT (active = le processus vit)."
	echo "Nom D-Bus: l'application repond-elle sur le bus. « non » avec un reglage"
	echo "           « resident » et une unite « active » = le mode resident ne"
	echo "           marche PAS pour cette application, quoi qu'en dise le reglage."
}

[ -r "$CONF" ] || { echo "$CONF introuvable — le paquet joyeuse-tweaks est-il installe ?" >&2; exit 1; }

case "${1:-etat}" in
etat | "")
	etat
	;;
resident | froid)
	mode=$1
	[ "$#" -ge 2 ] || usage
	id=$(resoudre "$2") || exit 1
	ecrire_mode "$id" "$mode" || exit 1
	unite="redrtos-appli@${id}.service"
	if [ "$mode" = resident ]; then
		echo "→ $id devient RESIDENTE. Demarrage…"
		if systemctl --user start "$unite"; then
			# Ceinture et bretelles, et il faut dire laquelle est laquelle.
			# La CEINTURE est dans l'unite : redrtos-appli@.service est en
			# Type=dbus avec BusName=%i, donc systemd ne rend la main que quand
			# le nom est REELLEMENT pris. Le code de retour 0 prouve donc
			# quelque chose ici — c'est l'exception, pas la regle.
			# ☠️ Les BRETELLES sont ce test, et elles servent le jour ou
			#    quelqu'un passera l'unite en Type=simple « pour que ca demarre
			#    plus vite ». Ce jour-la le 0 ne prouvera plus rien, l'unite
			#    sera « active » sans detenir le nom, toucher l'icone lancera un
			#    SECOND processus, et RIEN ne le dira. Le message ci-dessous est
			#    ecrit pour ce jour-la.
			if busctl --user list --acquired --no-pager --no-legend 2>/dev/null \
				| awk '{ print $1 }' | grep -qx "$id"; then
				echo "✓ $id est residente et detient son nom D-Bus."
			else
				echo "⚠ L'unite $unite tourne, mais $id NE DETIENT PAS son nom D-Bus." >&2
				echo "  Le mode resident ne marche pas pour cette application :" >&2
				echo "  toucher l'icone lancera un SECOND processus." >&2
				echo "  A regarder : le nom du .desktop, du .service D-Bus et" >&2
				echo "  celui que l'application prend reellement doivent coincider." >&2
				exit 1
			fi
		else
			echo "⚠ L'unite $unite n'a pas demarre." >&2
			echo "  Regarde : systemctl --user status $unite" >&2
			echo "  Le reglage est ecrit ; l'application reste utilisable A FROID." >&2
			exit 1
		fi
	else
		echo "→ $id repasse A FROID. Arret…"
		systemctl --user stop "$unite" 2>/dev/null
		echo "✓ $id ne tournera plus en permanence (elle demarre a la demande)."
	fi
	;;
appliquer)
	exec /usr/lib/joyeuse-tweaks/residentes.sh
	;;
*)
	usage
	;;
esac
