#!/bin/bash
# rcrsn51 2012-07-01
# jamesbond Jan 2013, 2015 - fixes
#131117-2015-10-23 L18L internationalisation
# JakeSFR 2020 - handle direct/ram separately, detect savefile on encrypted
#                device, add btrfscompress param, dynamic GUI
# JakeSFR 2022 - auto-detect multisession, minor corrections and improvements

export TEXTDOMAIN=fatdog

# performance tweak - use "C" if there is no localisation
! [ -e $TEXTDOMAINDIR/${LANG%.*}/LC_MESSAGES/$TEXTDOMAIN.mo ] &&
! [ -e $TEXTDOMAINDIR/${LANG%_*}/LC_MESSAGES/$TEXTDOMAIN.mo ] && LANG=C

. $BOOTSTATE_PATH				# MULTI_PREFIX
export MULTI_PREFIX

TITLE="$(gettext 'Savefile Argument Builder')"
[ $(id -u) -ne 0 ] && exec gtksu "$TITLE" "$0" "$@"

build_argument() {

	if [ ! "$SAVEFILE" ] || [ ! -e "$SAVEFILE" ]; then
		echo; return
	fi

	# foolproof way to split find savedevice and savefile path
	mountpoint= prevpath=
	savefile="$(readlink -f "$SAVEFILE")"	# to handle /mnt/home/...
	savefile=${savefile#/}

	until [ "$prevpath" = "$savefile" ]; do 
		mountpoint=${mountpoint}/${savefile%%/*}
		prevpath=$savefile
		savefile=${savefile#*/}
		#echo $mountpoint -- $fullpath
		busybox mountpoint -q $mountpoint && break
	done
	partition=$(busybox mountpoint -n $mountpoint | awk '{print $1}')

	if [ ${partition%/*} ] && [ ${partition%/*} == "/dev/mapper" ]; then # LVM, translate to /dev/dm-x
		dmdev=$(ls -l /dev/mapper 2> /dev/null | awk -v dmdev=${partition##*/} '$10 == dmdev {print "/dev/dm-" $6; exit; }')
		[ "$dmdev" ] || dmdev=$(ls -l /dev/mapper 2>/dev/null | awk -v dmdev=${partition##*/} '$(NF-2) == dmdev {sub(/.*\//,"",$NF); print "/dev/" $NF; exit;}')
		partition=$dmdev
	fi

	if [ "$(lsblk -l | grep -w "$mountpoint" | awk '{print $6}')" = "crypt" ]; then
		crypt=":dmcrypt"
		partition="$(lsblk -l -p -o PKNAME,KNAME | grep -w "$partition" | awk '{print $1}')"
	else
		crypt=""
	fi

	if [ "$HDD" = "true" ] && ([ -z "$partition" ] || [ "$partition" = "UNKNOWN" ]); then
		Xdialog --title " " --msgbox "$(gettext 'I could not identify the partition for this savefile/savefolder/SFS!')" 0 0		
		echo; return
	else
		uuid=$(blkid -s UUID -o value $partition)
		if [ -z "$uuid" ] || [ -z "$partition" ]; then
			Xdialog --title " " --msgbox "$(gettext 'I could not identify the UUID of this savefile/savefolder/SFS!')" 0 0
			echo; return
		fi
	fi
	
	if [ "$RAM" = "true" ]; then
		mode="ram"
	else
		mode="direct"
	fi
	
	if [ "$ZLIB" = "true" ]; then
		comp="btrfscompress=zlib "
	elif [ "$LZO" = "true" ]; then
		comp="btrfscompress=lzo "
	elif [ "$ZSTD" = "true" ]; then
		comp="btrfscompress=zstd "
	else
		comp=""
	fi

	if echo "${savefile##*/}" | grep -qE "^${MULTI_PREFIX}.*(base|save).sfs$"; then
		multi=":multi"
		crypt=""							# multisession doesn't support encryption
		infix="${savefile##*/}"				# get rid of leading dir(s)
		infix="${infix#*${MULTI_PREFIX}}"	# get rid of 'multi-' prefix
		infix="${infix%%-[0-9]*}"				# get the actual infix
		# merge leading dir(s), if any, with infix
		if [ "$savefile" != "${savefile%/*}" ]; then
			savefile="${savefile%/*}/${infix}"
		else
			savefile="$infix"			
		fi
	else
		multi=""
	fi
	
	if [ "$HDD" = "true" ]; then
		ARGUMENT="${comp}savefile=${mode}${multi}:device:${partition#/dev/}:${savefile}${crypt}"
	else
		ARGUMENT="${comp}savefile=${mode}${multi}:uuid:${uuid}:${savefile}${crypt} waitdev=5"
	fi
	
	echo "$ARGUMENT"

}
export -f build_argument

export MAINDIALOG='
<window title="'${TITLE}'" resizable="false">
	<hbox>
		<vbox spacing="2">
			<text><label>'$(gettext "Use this applet if you have created a savefile, savefolder or multisession, but your bootloader cannot find it.")' </label></text>

			<frame '$(gettext "Instructions")'>
				<text xalign="0"><label>'$(gettext "1. Mount the required partition(s).")'</label></text>
				<text xalign="0"><label>'$(gettext "2. Move your savefile/savefolder/SFSes to the correct location.")'</label></text>
			</frame>
			
			<frame '$(gettext "3. Drag your savefile, savefolder or SFS into this box")'>
				<hbox>
					<entry fs-action="file" fs-folder="'${HOME}'" secondary-icon-stock="gtk-clear">
						<variable>SAVEFILE</variable>
						<input>echo $INPUT</input>
						<action signal="secondary-icon-release">clear:SAVEFILE</action>
						<action>refresh:OUTPUT</action>
					</entry>
					<button>
						<input file stock="gtk-open"></input>
						<action>show:CHOOSER</action>
						<action>hide:MAIN_GUI</action>
					</button>
				</hbox>
			</frame>
			
			<frame '$(gettext "4. Select the device type")'>
				<hbox>
					<radiobutton> 
						<variable>HDD</variable>
						<label>'$(gettext "Hard Drive (device)")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
					<text space-expand="true" space-fill="true"><label>""</label></text>
					<radiobutton>    
						<variable>USB</variable>
						<label>'$(gettext "USB (uuid)")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
				</hbox>
			</frame>
			
			<frame '$(gettext "5. Select layering mode")'>
				<hbox>
					<radiobutton>
						<variable>DIRECT</variable>
						<label>'$(gettext "Direct (good for HDD)")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
					<text space-expand="true" space-fill="true"><label>""</label></text>
					<radiobutton>
						<variable>RAM</variable>
						<label>'$(gettext "Ram (good for USB)")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
				</hbox>
			</frame>
			
			<frame '$(gettext "6. Btrfs compression (for btrfs-formatted savefiles)")'>
				<hbox>
					<radiobutton>
						<variable>NONE</variable>
						<label>'$(gettext "None")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
					<text space-expand="true" space-fill="true"><label>""</label></text>
					<radiobutton>
						<variable>ZLIB</variable>
						<label>'$(gettext "ZLIB")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
					<text space-expand="true" space-fill="true"><label>""</label></text>
					<radiobutton>
						<variable>LZO</variable>
						<label>'$(gettext "LZO")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
					<text space-expand="true" space-fill="true"><label>""</label></text>
					<radiobutton>
						<variable>ZSTD</variable>
						<label>'$(gettext "ZSTD")'</label>
						<action>if true refresh:OUTPUT</action>
					</radiobutton>
				</hbox>
			</frame>
						
			<frame>
				<text xalign="0"><label>'$(gettext "Here is your savefile argument:")'</label></text>
				<hbox>
					<entry editable="false">
						<variable>OUTPUT</variable>
						<input>build_argument</input>
					</entry>
					<button tooltip-text="'$(gettext "Copy to clipboard")'">
						<input file stock="gtk-copy"></input>
						<action>echo -n "$OUTPUT" | xsel -i -b</action>
					</button>
				</hbox>
				<vbox spacing="1">
					<text xalign="0"><label>'$(gettext "Use Ctrl-A, Ctrl-C and Ctrl-V keys to copy and paste it into your GRUB(4DOS) grub.cfg/menu.lst file.")'</label></text>
					<text xalign="0"><label>'$(gettext "Add it to the end of the \"linux\" or \"kernel\" line.")'</label></text>
					<text xalign="0"><label>'$(gettext "For a USB syslinux.cfg file, add it to the \"append\" line.")'</label></text>
				</vbox>
			</frame>
			
			<hbox>
				<button>
					<label>'$(gettext "Help")'</label>
					<input file stock="gtk-help"></input>
					<action>mdview /usr/share/doc/fd-help/boot-options-savefile.md "" "'$(gettext "Fatdog Help")'" &</action>
				</button>
				<button>
					<label>'$(gettext "Quit")'</label>
					<input file stock="gtk-quit"></input>
				</button>
			</hbox>
			
			<variable>MAIN_GUI</variable>
		</vbox>
	
		<vbox space-fill="true" space-expand="true">
			<chooser>
				<variable>INPUT</variable>
				<default>'${HOME}'</default>
				<width>600</width>
				<height>480</height>
			</chooser>
	
			<hbox space-fill="false" space-expand="false">
				<button>
					<label>'$(gettext 'OK')'</label>
					<input file stock="gtk-ok"></input>
					<action>refresh:SAVEFILE</action>
					<action>hide:CHOOSER</action>
					<action>show:MAIN_GUI</action>
				</button>
				<button>
					<label>'$(gettext 'Cancel')'</label>
					<input file stock="gtk-cancel"></input>
					<action>hide:CHOOSER</action>
					<action>show:MAIN_GUI</action>
				</button>
			</hbox>
			
			<variable>CHOOSER</variable>
		</vbox>

	</hbox>
	
	<action signal="realize">hide:CHOOSER</action>
</window>
'

gtkdialog --program MAINDIALOG
exit
