#!/bin/sh

###################################################################################################
# THIS MODULE INCLUDES ALL ACTIONS INTENDED TO ISOLATE DOTFILES OR CONTAINERIZE INSTALLED APPIMAGES
###################################################################################################

# Get xdg variables for _configure_dirs_access
for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do
	eval XDG_DIR="$(xdg-user-dir $DIR 2>/dev/null)"
	[ "$XDG_DIR" = "$HOME" ] || [ "$XDG_DIR" = "$HOME/" ] && XDG_DIR=""
	eval $DIR="$XDG_DIR"
done
DESKTOP="$(echo "${DESKTOP:-~/Desktop}" | sed "s|$HOME|~|g")"
DOCUMENTS="$(echo "${DOCUMENTS:-~/Documents}" | sed "s|$HOME|~|g")"
DOWNLOAD="$(echo "${DOWNLOAD:-~/Downloads}" | sed "s|$HOME|~|g")"
GAMES="$(echo "${GAMES:-~/Games}" | sed "s|$HOME|~|g")"
MUSIC="$(echo "${MUSIC:-~/Music}" | sed "s|$HOME|~|g")"
PICTURES="$(echo "${PICTURES:-~/Pictures}" | sed "s|$HOME|~|g")"
VIDEOS="$(echo "${VIDEOS:-~/Videos}" | sed "s|$HOME|~|g")"

_check_appimage() {
	_determine_args
	TARGET="$(command -v "$1")"
	APPIMAGEDIR=$(echo "$ARGPATHS" | grep "/$1$")
	APPIMAGE="$APPIMAGEDIR/$1"
	if [ ! -d "$APPIMAGEDIR" ]; then
		echo " ERROR: \"$1\" is not installed"
		return 1
	elif ! strings -d "$APPIMAGE" | grep -- '--appimage-extract' 1>/dev/null; then
		echo " ERROR: \"$1\" is NOT an AppImage"
		return 1
	fi
}

_home() {
	if [ -d "$APPIMAGE.home" ]; then
		echo " ERROR: \"$1\" already contains a home dir"
		return 1
	fi
	mkdir "$APPIMAGE.home" || return 1
	echo " \$HOME set to \"$APPIMAGE.home\" for \"$1\""
}

_config() {
	if [ -d "$APPIMAGE.config" ]; then
		echo " ERROR: \"$1\" already contains a config dir"
		return 1
	fi
	mkdir "$APPIMAGE.config" || return 1
	echo " \$XDG_CONFIG_HOME set to \"$APPIMAGE.config\" for \"$1\""
}

_disable_sandbox() {
	TARGET="$(command -v "$1")"
	if ! grep "aisap-am sandboxing script" "$TARGET" >/dev/null 2>&1; then
		echo " ERROR: Not a sandboxed AppImage, aborting" 
		return 1
	fi
	"$1" --disable-sandbox
}

_check_aisap() {
	if [ "$1" = "aisap" ]; then
		echo " Error: You can't sandbox aisap"
		return 1
	elif ! command -v aisap 1>/dev/null; then
		printf '\n%s\n\n' " Error: You need aisap for this script work"
		read -r -p " ◆ DO YOU WISH TO INSTALL AISAP? Install size <5 MiB? (Y/n) " yn
		if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
			echo " OPERATION ABORTED!"
			return 1
		fi
		"$AMCLIPATH" -i aisap >/dev/null 2>&1
		command -v aisap 1>/dev/null || return 1 
		echo " aisap installed successfully!"
	fi	
	if grep "aisap-am" "$TARGET" >/dev/null 2>&1; then
		echo " $1 is already sandboxed!"
		return 1
	fi
}

_generate_sandbox_script() {
	echo "$DIVIDING_LINE"
	printf '\n%s\n' " Making aisap sandbox script for \"$1\"..."
	tmpscript="$(cat <<-'HEREDOC'
	#!/bin/sh
	# aisap-am sandboxing script, aisap: https://github.com/mgord9518/aisap
	# Thanks a lot to mgord9518 for making aisap!
	# Run this script with --disable-sandbox to do what the flag name implies
	# The default location for the sandboxed home is in $HOME/.local/am-sandboxes
	# But that location can be changed by setting the $SANDBOXDIR env variable

	# Dependency check
	if ! command -v aisap 1>/dev/null; then
	  echo "You need aisap for this to work"
	  notify-send -u critical "Sandbox error: Missing aisap dependency!"
	  exit 1
	fi
	# Set variables and create sandboxed dir.
	APPEXEC=DUMMY
	chmod a-x "$APPEXEC" # Prevents accidental launch of app outside the sandbox
	APPNAME="$(echo "$APPEXEC" | awk -F "/" '{print $NF}')"
	SANDBOXDIR="${SANDBOXDIR:-$HOME/.local/am-sandboxes}"
	DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}"
	CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}"
	CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}"
	DBUS="$(ls /tmp/dbus* 2>/dev/null | head -1)"
	# get xdg user dirs, unset if var = $HOME
	for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do
	  eval XDG_DIR="$(xdg-user-dir $DIR 2>/dev/null)"
	  [ "$XDG_DIR" = "$HOME" ] || [ "$XDG_DIR" = "$HOME/" ] && XDG_DIR=""
	  eval $DIR="$XDG_DIR"
	done	
	# Use default location if var is not set
	DESKTOP="${DESKTOP:-~/Desktop}"
	DOCUMENTS="${DOCUMENTS:-~/Documents}"
	DOWNLOAD="${DOWNLOAD:-~/Downloads}"
	GAMES="${GAMES:-~/Games}"
	MUSIC="${MUSIC:-~/Music}"
	PICTURES="${PICTURES:-~/Pictures}"
	VIDEOS="${VIDEOS:-~/Videos}"
	# Try find the right name of the app conf/data dir
	APPDATA=$( ls "$DATADIR" | grep -i "$APPNAME" | head -1 )
	APPCONF=$( ls "$CONFIGDIR" | grep -i "$APPNAME" | head -1 ) 
	# Disable sandbox
	if [ "$1" = "--disable-sandbox" ]; then
	  APPIMAGEDIR="${APPEXEC%/*}"
	  echo ""
	  echo " Giving exec permissions back to $APPEXEC..."
	  chmod a+x "$APPEXEC" || exit 1
	  echo " Patching $APPIMAGEDIR/AM-updater to give permissions back..."
	  sed -i 's|chmod a-x|chmod a+x|g' "$APPIMAGEDIR/AM-updater" || exit 1
	  THISFILE="$(realpath "$0")"
	  echo " Replacing $THISFILE with a link to the AppImage..."
	  SUDO ln -sf "$APPEXEC" "$THISFILE" || exit 1
	  printf '\033[32m\n%s\n\033[0m\n' " $APPEXEC successfully unsandboxed!"
	  exit 0
	fi
	mkdir -p "$SANDBOXDIR/$APPNAME"
	[ -z "$APPNAME" ] && exit 1
	# Start at sandboxed home
	# Edit below this to add or remove access to parts of the system
	exec aisap --trust-once --level 2 \
	--data-dir "$SANDBOXDIR/$APPNAME" \
	--add-file "$DATADIR/${APPDATA:-$APPNAME}":rw \
	--add-file "$DATADIR"/themes \
	--add-file "$DATADIR"/icons \
	--add-file "$CONFIGDIR/${APPCONF:-$APPNAME}":rw \
	--add-file "$CONFIGDIR"/dconf \
	--add-file "$CONFIGDIR"/gtk3.0 \
	--add-file "$CONFIGDIR"/gtk4.0 \
	--add-file "$CONFIGDIR"/kdeglobals \
	--add-file "$CONFIGDIR"/qt5ct \
	--add-file "$CONFIGDIR"/qt6ct \
	--add-file "$CONFIGDIR"/Kvantum \
	--add-file "$HOME"/.local/lib \
	--add-file /usr/share \
	--rm-file /NOPATH \
	--rm-file "$DESKTOP" \
	--rm-file "$DOCUMENTS" \
	--rm-file "$DOWNLOAD" \
	--rm-file "$GAMES" \
	--rm-file "$MUSIC" \
	--rm-file "$PICTURES" \
	--rm-file "$VIDEOS" \
	--add-file /var/lib/dbus \
	--add-file "${DBUS:-/tmp/dbus}" \
	--add-socket pulseaudio \
	--add-socket dbus \
	--add-socket network \
	--add-socket x11 \
	--add-socket wayland \
	--add-device dri -- \
	"$APPEXEC" "$@"
	HEREDOC
	)"
}

_configure_dirs_access() {
	printf '\033[33m\n'
	read -r -p " Do you want configure access to directories? (Y/n): " yn
	if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
		return 0
	fi
	printf '\033[36m'
	for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do
		eval XDG_DIR=\$$DIR
		read -r -p " Allow $1 access to \"$XDG_DIR\"? (y/N) " yn
		if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
			tmpscript=$(echo "$tmpscript" \
				| sed "s#--rm-file \"\$$DIR\"#--add-file \"\$$DIR\":rw#g" )
		fi
	done
	sleep 0.5
	printf '\033[31m'
	read -r -p " Allow $1 access to a specific directory? (y/N) " yn
	if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
		echo "  WARNING: Giving access to all of $HOME or / and similar is not safe"
		echo "  Also aisap might not let $1 start when such paths are given"
		printf '\033[33m%s\n' "  Type the path to the directory"
		read -r -p "  Example: /media/external-drive or ~/Backups: " NEWDIR
		case "$NEWDIR" in
			'$HOME'|'$HOME/'|"$HOME"|"$HOME/"|"/"|"~"|"~/"|"/home"|"/home/"|\
			"$DATADIR"|'$XDG_DATA_HOME'|"$CONFIGDIR"|'$XDG_CONFIG_HOME'|"$BINDIR")
				notify-send -u critical "DO YOU WANT THE FBI TO GET YA?"
				printf '\033[31m\n' 
				read -r -p "  SPOOKY LOCATION! ARE YOU SURE? IF SO TYPE \"YES\": " YES
				[ "$YES" != "YES" ] && echo " That's not \"YES\", aborting" && return 1
				;;
			'')
				printf '\033[31m\n%s\n\n' " No path given, aborting"
				return 1
				;;
		esac
		echo "  Giving access to \"$NEWDIR\"..."
		tmpscript=$(echo "$tmpscript" \
			| sed "s#--rm-file /NOPATH#--add-file \"$NEWDIR\":rw#g")
	fi
	printf '\n\033[32m%s\n' " User directories access configured successfully!"
}

_install_sandbox_script() {
	tmpscript=$(echo "$tmpscript" | sed "s#DUMMY#$APPIMAGE#g; s#SUDO#$SUDOCMD#g")
	# Remove exec permission from AppImage and its updater for better safety™
	chmod a-x "$APPIMAGE" || return 1
	sed -i 's|chmod a+x|chmod a-x|g' "$APPIMAGEDIR/AM-updater" || return 1
	# Install the script
	$SUDOCMD rm -f "$TARGET" || return 1
	echo "$tmpscript" | $SUDOCMD tee "$TARGET" >/dev/null 2>&1 || return 1
	$SUDOCMD chmod a+x "$TARGET"
	SANDBOXDIR="${SANDBOXDIR:-$HOME/.local/am-sandboxes}"
	printf '\033[32m\n%s\n\033[0m' " \"$1\" successfully sandboxed!"
	printf '\n%s\n' " $1 will be sandboxed in \"$SANDBOXDIR\""
	printf '%s\n\n' " once launched"
	printf '%s\n' " Set the \$SANDBOXDIR env variable to move the location"
	printf '\n%s' ' Use '
	printf '\033[33m%s' '--disable-sandbox'
	printf '\033[0m%s\033[33m\n' " to revert the changes, in this case that is:"
	printf '\033[33m%s\033[0m' " $1 --disable-sandbox"
	printf '%s\033[33m%s\n\033[0m\n' " or " "$AMCLI --disable-sandbox $1"
}

# Main logic
[ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1
case "$1" in
	'--sandbox')
		shift
		while [ "$#" -gt 0 ]; do
			_check_appimage "${@}" && _check_aisap "${@}" \
			&& _generate_sandbox_script "${@}" \
			&& _configure_dirs_access "${@}" \
			&& _install_sandbox_script "${@}"
			shift
		done
	;;

	'--disable-sandbox')
		shift
		while [ "$#" -gt 0 ]; do
			echo "$DIVIDING_LINE"
			_disable_sandbox "${@}"
			shift
		done
		;;

	'-H'|'--home')
		shift
		while [ "$#" -gt 0 ]; do
			_check_appimage "${@}" && _home "${@}"
			shift
		done
		;;

	'-C'|'--config')
		shift
		while [ "$#" -gt 0 ]; do
			_check_appimage "${@}" && _config "${@}"
			shift
		done
		;;
esac
_remove_info_files
