#!/bin/ash

# SFS Exec version 0.8
# A wrapper script to automatically load, run and unload an SFS in Fatdog64
# Copyright © JakeSFR 2020,2021
# License: GPL vesion 3 - see http://www.gnu.org/licenses/gpl.html

export TEXTDOMAIN=fatdog
export OUTPUT_CHARSET=UTF-8

. gettext.sh

APPTITLE="SFS Exec"
APPPATH="$0"
CONFIG="${XDG_CONFIG_HOME}/sfsexec.conf"
ROX_SFS="${XDG_CONFIG_HOME}/rox.sourceforge.net/SendTo/.application_x-squashfs-image"
ROX_MIME="${XDG_CONFIG_HOME}/rox.sourceforge.net/MIME-types"
SFSPATH="$(readlink -f "$1")"
SFSNAME="${SFSPATH##*/}"

HARDSPACE="$(echo -ne '\xc2\xa0')"	# to replace spaces with hard spaces, for Xdialog

WELCOME_MSG="$(eval_gettext "This utility can automatically load, \
execute and (upon closing an app) unload an SFS.

By default, the *.desktop file within an SFS is automatically
detected and the application is launched without user intervention.

If there's no *.desktop file in the SFS, you'll be asked to provide the name
of the command to launch, which will be stored in the configuration file
\${HOME}/.config/sfsexec.conf.

There are several ways to use this utility:
- drag and drop an SFS onto this script (it's in \${APPPATH})
- execute it from CLI providing a full path to an SFS as an argument
- create a *.desktop file for a given SFS that contains 'Exec=sfsexec /path/to/SFS'
- associate SFS Exec with ROX left/right-click action (see the next dialog).")"

WELCOME_OPTS="
edit|$(gettext "Edit config file")
assoc|$(gettext "Associate SFS Exec with ROX left-click action")
deassoc|$(gettext "Dissociate SFS Exec from ROX left-click action")
addrtmenu|$(gettext "Add SFS Exec to ROX right-click menu")
remrtmenu|$(gettext "Remove SFS Exec from ROX right-click menu")
"
WELCOME_OPTS="${WELCOME_OPTS// /${HARDSPACE}}"

PUP_RO=pup_ro
[ -e $BOOTSTATE_PATH ] && . $BOOTSTATE_PATH	# AUFS_ROOT_ID

# If there's no config file or it's empty, add an info about the syntax to it
if [ ! -e "$CONFIG" ] || [ ! -s "$CONFIG" ]; then
	echo "$(gettext "# Syntax: name_of_the_sfs:name_of_the_executable")" > "$CONFIG"
fi

# If no args, display welcome screen followed by some additional actions
if [ ! "$SFSPATH" ]; then
	Xdialog --title "$APPTITLE" --ok-label="$(gettext "Continue")" --left -msgbox "$WELCOME_MSG" 0 0
	[ $? -eq 255 ] && exit

	RESULT=$(Xdialog --stdout --no-tags \
					 --title "$APPTITLE" \
					 --menubox "$(gettext "Choose an action:")" 12 50 5 \
					 ${WELCOME_OPTS//|/ })
	[ $? -ne 0 ] && exit

	case "$RESULT" in
		edit)		defaulttexteditor "$CONFIG"
					;;
		assoc)		mkdir -p "$ROX_MIME"
					ln -sf "$(readlink -f "$0")" "${ROX_MIME}/application_x-squashfs-image"
					;;
		deassoc)	rm -f "${ROX_MIME}/application_x-squashfs-image"
					;;
		addrtmenu)	mkdir -p "$ROX_SFS"
					ln -sf "$(readlink -f "$0")" "${ROX_SFS}/${APPTITLE}"
					echo '<?xml version="1.0"?>
					<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
					<env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">
					<SetIcon><Path>'${ROX_SFS}/${APPTITLE}'</Path>
					<Icon>/usr/share/pixmaps/midi-icons/squashfs-image48.png</Icon>
					</SetIcon></env:Body></env:Envelope>' | rox -R
					;;
		remrtmenu)	rm -f "${ROX_SFS}/${APPTITLE}"
					echo '<?xml version="1.0"?>
					<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
					<env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">
					<UnsetIcon><Path>'${ROX_SFS}/${APPTITLE}'</Path>
					</UnsetIcon></env:Body></env:Envelope>' | rox -R
					;;
	esac

	exit
fi

# Check if the SFS is already loaded
if load_sfs.sh --list | grep -Fq "${SFSPATH}"; then
	SFS_ALREADY_LOADED='true'
else
	SFS_ALREADY_LOADED=''
fi

# Load SFS
if [ ! "$SFS_ALREADY_LOADED" ] && ! load_sfs.sh --quiet --load "$SFSPATH"; then
	Xdialog --title "$APPTITLE" \
			--backtitle "$(gettext "Error!")" \
			--infobox "$(eval_gettext "Unable to load \${SFSNAME}. Aborting...")" 0 0 10000
	exit 1
fi

# Lookup for exec name for a given SFS in config file
SFSEXEC="$(grep -v '^#' "$CONFIG" | grep -m1 "^${SFSNAME}:" 2>/dev/null)"
SFSEXEC="${SFSEXEC##*:}"

# No exec in config file -> lookup for one in .desktop file(s)
if [ ! "$SFSEXEC" ]; then
	# mountpoint lookup (borrowed from load_sfs.sh)
	for p in $(sed -n "/$PUP_RO/{s|=.*||;p}" /sys/fs/aufs/$AUFS_ROOT_ID/br[0-9]*); do
		case "$(cat /sys/block/loop${p#*$PUP_RO}/loop/backing_file 2> /dev/null)" in
			*"$SFSPATH"*) MNTPT="$p"; break;
		esac
	done

	SFSEXEC=$(find "$MNTPT" -type f -iname "*.desktop" -exec sed -n 's/^Exec=\(.*\)/\1/p' {} \; | sed 's/ %.*//' | sort -u)

	if [ $(echo "$SFSEXEC" | grep -c .) -gt 1 ]; then
		MENU=$(echo "$SFSEXEC" | while read ITEM; do
			echo "${ITEM// /${HARDSPACE}} ${ITEM// /${HARDSPACE}}"
		done)

		SFSEXEC=$(Xdialog --stdout --no-tags \
						  --title "$APPTITLE" \
						  --check "$(gettext "Remember my choice next time")" off \
						  --menubox "$(gettext "Please choose an executable to run:")" 15 40 5 $MENU)

		CHECK="$(echo "$SFSEXEC" | tail -n 1)"
		SFSEXEC="$(echo "$SFSEXEC" | head -n 1)"
		SFSEXEC="${SFSEXEC//${HARDSPACE}/ }"

		if [ $? -ne 0 ] || [ ! "$SFSEXEC" ]; then
			[ ! "$SFS_ALREADY_LOADED" ] && load_sfs.sh --quiet --unload "$SFSPATH"
			exit
		fi

		[ "$CHECK" = 'checked' ] && echo "${SFSNAME}:${SFSEXEC}" >> "$CONFIG"

	fi
fi

# No exec in config file and no .desktop file(s), so provide the name of the executable manually
if [ ! "$SFSEXEC" ]; then
	MSG="$(eval_gettext "Please provide the name of the executable for \${SFSNAME}.\nIt's a one-time procedure.")"
	SFSEXEC="$(Xdialog --stdout --title "$APPTITLE" --inputbox "$MSG" 0 0)"
	if [ $? -ne 0 ] || [ ! "$SFSEXEC" ]; then
		[ ! "$SFS_ALREADY_LOADED" ] && load_sfs.sh --quiet --unload "$SFSPATH"
		exit
	fi
	echo "${SFSNAME}:${SFSEXEC}" >> "$CONFIG"
fi

# Get rid of any leading/trailing spaces, just in case,
# because trailing spaces in config file can be hard to notice.
# But keep the spaces within, to support e.g. 'defaultterm -e some_app'.
SFSEXEC="$(echo "$SFSEXEC" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"

# Execute
${SFSEXEC}

# Unload the SFS
[ ! "$SFS_ALREADY_LOADED" ] && load_sfs.sh --quiet --unload "$SFSPATH"

exit
