#!/bin/bash

###############################################################################
# AppRun for UExtract														  #
# Copyright © JakeSFR 2013-2026												  #
# License: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html			  #
###############################################################################

MYPATH="$(dirname "$(readlink -f "$0")")"
APPNAME="$(sed -n '4 {s/# \(.*[^[:blank:]]\)[[:blank:]].*/\1/p}' "${MYPATH}/uextract")"
ICON="${MYPATH}/UExtract.png"

export TEXTDOMAINDIR="${MYPATH}/locale"
export TEXTDOMAIN=uextract
export OUTPUT_CHARSET=UTF-8

WORKDIR="${TMPDIR:-/tmp}/uextract_apprun.${USER}.${$}"
TMPEXEC="${WORKDIR}/uextract_exec_${USER}.${$}"

# For YAD
YAD_BIN=${YAD_BIN:-yad}
YAD_VERSION="$($YAD_BIN --version 2>/dev/null)"

f_source_hidpi() {
	# IF GTK2 || GTK3 && GDK_SCALE < 2 or unset
	if [ "${YAD_VERSION#*GTK+ 2}" != "$YAD_VERSION" -o "${GDK_SCALE:-1}" = 1 ] &&
		type fatdog-hidpi-lib >/dev/null 2>&1;
	then
		. fatdog-hidpi-lib
	else
		hidpi_apply_scale() { echo "$@"; }	# stub
	fi
}
export -f f_source_hidpi
f_source_hidpi

if ! type gettext >/dev/null 2>&1; then
	gettext() { echo "$@"; };
	export -f gettext
fi

if ! mkdir -p "$WORKDIR"; then
	echo "$(gettext 'Cannot create temporary directory! Aborting...')"
	exit 1
fi

CUR_LANG="${LANG:0:2}"
[ "$LANGUAGE" ] && CUR_LANG="${LANGUAGE:0:2}"

BACKENDS="${WORKDIR}/backends"
DEPENDENCIES="${WORKDIR}/dependencies"
LINKS="${MYPATH}/doc/LINKS.txt"
FILETYPES="${MYPATH}/doc/FILETYPES.txt"
if [ -f "${MYPATH}/doc/FILETYPES_${CUR_LANG}.txt" ]; then
	FILETYPES="${MYPATH}/doc/FILETYPES_${CUR_LANG}.txt"
fi

GUI="${UEXTRACT_GUI:-Xdialog}"	# fallback

if type ${YAD_BIN} >/dev/null 2>&1; then
	[ -z "$UEXTRACT_GUI" ] && GUI=yad
fi

# My name is Legion, because there are many of us
for GTKDIALOG in gtkdialog4 gtkdialog gtk2dialog gtkdialog_gtk2 gtkwialog gtkdialog3; do
	if type "$GTKDIALOG" >/dev/null 2>&1; then
		[ -z "$UEXTRACT_GUI" ] && GUI=gtkdialog
		break	
	fi
done

if [ "$GUI" = 'gtkdialog' ]; then
	GTKDLG_VER="$(LANG=C $GTKDIALOG --version 2>/dev/null)"

	# If gtkdialog is 0.7.20 or older, don't use hseparator/vseparator!
	GTKDLG_MIN_VER='0.7.21'
	GTKDLG_CUR_VER="$(echo "$GTKDLG_VER" | sed -n 's|.*version \([0-9\.]\+\) .*|\1|p')"
	if [ $(printf "%03d%03d%03d%03d%03d" ${GTKDLG_CUR_VER//./ }) -lt $(printf "%03d%03d%03d%03d%03d" ${GTKDLG_MIN_VER//./ }) ]; then
		HSEP=''
		VSEP=''
	else
		HSEP='<hseparator></hseparator>'
		VSEP='<vseparator></vseparator>'
	fi
	
	# Needed for GTK3 to make the text reasonably wide, so it doesn't wrap every 5 chars or so,
	# but it breaks GTK2, so have to apply accordingly
	if echo "$GTKDLG_VER" | grep -qw 'GTK+ 3'; then
		GTK3_FIX=' space-fill="true" space-expand="true"'
	else
		GTK3_FIX=''
	fi
	
	# Check for VTE availability
	if echo "$GTKDLG_VER" | grep -qw 'VTE'; then
		GTKDLG_VTE='true'
	else
		GTKDLG_VTE='false'
	fi
	
fi

# Custom GTK2/3 styles for textview (also for Xdialog)
mkdir -p "${WORKDIR}/gtk-3.0"

# GTK2
CUSTOM_GTK2="${WORKDIR}/gtkrc"
cat > "$CUSTOM_GTK2" <<EOF
style 'fixed_font' {
font_name="Monospace"
}
widget '*Text*' style 'fixed_font'
class '*GtkText*' style 'fixed_font'
EOF

# GTK3
CUSTOM_GTK3="${WORKDIR}/gtk-3.0/gtk.css"
cat > "$CUSTOM_GTK3" <<EOF
textview {
font-family: monospace;
}
EOF

YAD_KEY=''
YAD_PID=''

export MYPATH WORKDIR ICON CUSTOM_GTK2 APPNAME  FILETYPES LINKS BACKENDS DEPENDENCIES
export GUI GTKDIALOG YAD_BIN YAD_VERSION

# -----------------------------------------------------------------------------

f_trap() {
	[ -d "${WORKDIR}" ] && rm -rf "${WORKDIR}"
	[ "$YAD_PID" ] && kill -0 ${YAD_PID} 2>/dev/null && kill ${YAD_PID}
	[ "$YAD_KEY" ] && pkill -f "${YAD_BIN}.*--(key|plug)=${YAD_KEY} "
	[ "$YAD_KEY" ] && ipcrm -M ${YAD_KEY} 2>/dev/null
	exit
}

trap 'f_trap' 0 INT HUP TERM QUIT ABRT

# -----------------------------------------------------------------------------

f_show_dialog() {
	local g_width g_height y_width y_height x_width x_height label input_file tabnum tabs i i_cmd
	
	f_source_hidpi	# for YAD
	
	if [ "$1" = 'all' ]; then

		"${MYPATH}/uextract" -b | sed -r "s/\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]//g" | tail -n +5 | head -n -1 > "${BACKENDS}"
		"${MYPATH}/uextract" -d | sed -r "s/\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]//g" | tail -n +5 | head -n -1 > "${DEPENDENCIES}"

		if [ "$GUI" = 'gtkdialog' ]; then
	
			echo '
			<window title="'${APPNAME}'" image-name="'${ICON}'" window-position="1">
				<vbox>
					
					<notebook labels="'$(gettext 'Filetypes')'|'$(gettext 'Weblinks')'|'$(gettext 'Backends')'|'$(gettext 'Dependencies')'" space-fill="true" space-expand="true">
	
						<edit editable="false" cursor-visible="false">
							<width>780</width>
							<height>400</height>
							<input file>'${FILETYPES}'</input>
						</edit>
	
						<edit editable="false" cursor-visible="false">
							<input file>'${LINKS}'</input>
						</edit>
	
						<edit editable="false" cursor-visible="false">
							<input file>'${BACKENDS}'</input>
						</edit>
	
					</notebook>
	
					<hbox homogeneous="true" space-fill="false" space-expand="false">
						<button has-focus="true">
							<label>'$(gettext "Close")'</label>
							<input file stock="gtk-close"></input>
						</button>
					</hbox>
	
				</vbox>
			</window>
			' | GTK2_RC_FILES="${CUSTOM_GTK2}:${HOME}/.gtkrc-2.0" XDG_CONFIG_HOME="${WORKDIR}" $GTKDIALOG -s >/dev/null 2>&1 &
			
		elif [ "$GUI" = 'yad' ]; then
			
			YAD_KEY=$(( ${RANDOM} * ( $$ % 32768 ) ))
			tabnum=1
			tabs=''
			
			for i in "$(gettext "Filetypes")|FILETYPES" "$(gettext "Weblinks")|LINKS" "$(gettext "Backends")|BACKENDS"; do
				i_cmd="${i#*|}"
				
				${YAD_BIN} --plug=${YAD_KEY} --tabnum=${tabnum} --no-markup \
					--text="${i%|*}" --fontname='Monospace' \
					--text-info < "${!i_cmd}" &
				
				tabnum=$((tabnum+1))
				tabs="${tabs}--tab=$(echo "${i%|*}") "
			done
			
			${YAD_BIN} --title="${APPNAME}" --window-icon="${ICON}" \
				--width=$(hidpi_apply_scale 800) --height=$(hidpi_apply_scale 600) \
				--center --button="gtk-close" --buttons-layout="center" --escape-ok --no-markup \
				--notebook --tab-pos=top --key=${YAD_KEY} \
				${tabs} --active-tab=1
			
			pkill -f "${YAD_BIN}.*--(key|plug)=${YAD_KEY} "	# kill zombie processes, if any
			YAD_KEY=''
			
		fi
		
		return
	fi
	
	# g = gtkdialog; y = yad; x = Xdialog
	case "$1" in
		'filetypes')
			g_width=780
			g_height=400
			y_width=$(hidpi_apply_scale 800)
			y_height=$(hidpi_apply_scale 500)
			x_width=98
			x_height=32
			label="$(gettext 'Filetypes')"
			input_file="${FILETYPES}"
			;;

		'backends')
			g_width=400
			g_height=400
			y_width=$(hidpi_apply_scale 400)
			y_height=$(hidpi_apply_scale 480)
			x_width=51
			x_height=32
			label="$(gettext 'Backends')"
			input_file="${BACKENDS}"
			"${MYPATH}/uextract" -b | sed -r "s/\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]//g" | tail -n +5 | head -n -1 > "${BACKENDS}"
			;;

		'dependencies')
			g_width=400
			g_height=400
			y_width=$(hidpi_apply_scale 400)
			y_height=$(hidpi_apply_scale 480)
			x_width=51
			x_height=32
			label="$(gettext 'Dependencies')"
			input_file="${DEPENDENCIES}"
			"${MYPATH}/uextract" -d | sed -r "s/\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]//g" | tail -n +5 | head -n -1 > "${DEPENDENCIES}"
			;;

		'weblinks')
			g_width=780
			g_height=400
			y_width=$(hidpi_apply_scale 800)
			y_height=$(hidpi_apply_scale 500)
			x_width=98
			x_height=32
			label="$(gettext 'Weblinks')"
			input_file="${LINKS}"
			;;
	esac


	if [ "$GUI" = 'gtkdialog' ]; then

		echo '
		<window title="'${APPNAME}'" image-name="'${ICON}'" window-position="1">
			<vbox>

				<text use-markup="true">
					<label>"<span size='"'x-large'"'><b>'${label}'</b></span>"</label>
				</text>

				<edit editable="false" cursor-visible="false">
					<width>'${g_width}'</width>
					<height>'${g_height}'</height>
					<input file>'${input_file}'</input>
				</edit>

				<hbox homogeneous="true">
					<button has-focus="true">
						<label>'$(gettext "Close")'</label>
						<input file stock="gtk-close"></input>
					</button>
				</hbox>

			</vbox>
		</window>
		' | GTK2_RC_FILES="${CUSTOM_GTK2}:${HOME}/.gtkrc-2.0" XDG_CONFIG_HOME="${WORKDIR}" $GTKDIALOG -s #--styles "${CUSTOM_GTK}"	# not supported in older Gtkdialog versions
	
	elif [ "$GUI" = 'yad' ]; then
		
		${YAD_BIN} --title "$APPNAME" \
			--window-icon="${ICON}" \
			--width=${y_width} --height=${y_height} \
			--center --text-align=center \
			--text="<span size='"'x-large'"'><b>${label}</b></span>" \
			--buttons-layout=center \
			--button "gtk-close" \
			--fontname='Monospace' \
			--text-info < "${input_file}"
		
	else

		Xdialog --fixed-font \
				--rc-file "${CUSTOM_GTK2}" \
				--center \
				--no-cancel \
				--title "${APPNAME}" \
				--backtitle "${label}" \
				--textbox "${input_file}" "${x_height}" "${x_width}"

	fi

}

export -f f_show_dialog

# -----------------------------------------------------------------------------

f_input_files() {

	if [ "$GUI" = 'gtkdialog' ]; then

		CHOOSER="$(echo '
		<window title="'${APPNAME}'" image-name="'${ICON}'" window-position="1">
			<vbox>

				<text use-markup="true">
					<label>"<span size='"'x-large'"'><b>'$(gettext 'Select input file or directory')'</b></span>"</label>
				</text>

				'${HSEP}'

				<chooser action="0" space-fill="true" space-expand="true">
					<variable>varCHOOSER</variable>
					<default>'${HOME}'</default>
					<width>600</width>
					<height>400</height>
					<action when="file-activated">echo "CHOOSER=\"$varCHOOSER\""</action>
					<action when="file-activated">EXIT:OK</action>
				</chooser>

				<hbox space-fill="false" space-expand="false">

					<button space-fill="false" space-expand="false">
						<input file stock="gtk-info"></input>
						<action>f_show_dialog all</action>
					</button>

					<text space-fill="true" space-expand="true"><label>""</label></text>

					<hbox homogeneous="true" space-fill="true">
						<button ok>
							<action>echo "CHOOSER=\"$varCHOOSER\""</action>
							<action>closewindow:varCHOOSER</action>
						</button>
						<button cancel>
							<action>closewindow:varCHOOSER</action>
						</button>
					</hbox>
				</hbox>

			</vbox>

		</window>
		' | $GTKDIALOG -s)"

		IFILES="$(echo "$CHOOSER" | grep '^CHOOSER=' | sed -n 's/.*="\(.*\)"/\1/p')"
		eval $(echo "$CHOOSER" | grep '^EXIT=')
		
		if ([ "$EXIT" = 'closewindow' ] || [ "$EXIT" = 'OK' ]) && [ "$IFILES" ]; then
			return 0
		else
			return 1
		fi
		
	elif [ "$GUI" = 'yad' ]; then
		
		IFILES="$(${YAD_BIN} \
			--title "$APPNAME" \
			--window-icon="${ICON}" \
			--width=$(hidpi_apply_scale 600) --height=$(hidpi_apply_scale 500) \
			--center --text-align=center \
			--text "<span size='"'x-large'"'><b>$(gettext "Select input file or directory")</b></span>" \
			--button gtk-info:'bash -c "f_show_dialog all"' \
			--button gtk-ok:0 \
			--button gtk-cancel:1 \
			--file)"
		
		[ $? -eq 0 ] && return 0 || return 1
		
	else
		
		IFILES="$(Xdialog \
			--stdout \
			--no-buttons \
			--center \
			--title "$APPNAME" \
			--backtitle "$(gettext 'Select input file or directory')" \
			--fselect "" 0 0 2>/dev/null)"
		
		[ $? -eq 0 ] && return 0 || return 1
		
	fi

}

# -----------------------------------------------------------------------------

f_output_dir() {
	
	if [ "$GUI" = 'gtkdialog' ]; then

		CHOOSER="$(echo '
		<window title="'${APPNAME}'" image-name="'${ICON}'" window-position="1">
			<vbox>

				<text use-markup="true">
					<label>"<span size='"'x-large'"'><b>'$(gettext 'Select output directory')'</b></span>"</label>
				</text>

				<hbox homogeneous="true">
					<text'${GTK3_FIX}'>
						<variable>varSELECTION</variable>
						<input>echo -n "$varCHOOSER"</input>
					</text>
				</hbox>

				'${HSEP}'

				<chooser action="2" space-fill="true" space-expand="true">
					<variable>varCHOOSER</variable>
					<default>$(pwd)</default>
					<width>600</width>
					<height>400</height>
					<action when="selection-changed">refresh:varSELECTION</action>
				</chooser>

				<hbox space-fill="false" space-expand="false">

					<hbox space-fill="false" space-expand="false">
						<vbox homogeneous="true" space-fill="false" space-expand="false">
							<button space-fill="false" space-expand="false">
								<input file stock="gtk-info"></input>
								<action>f_show_dialog all</action>
							</button>
						</vbox>
						'${VSEP}'
					</hbox>

					<vbox spacing="0">
						<checkbox>
							<default>true</default>
							<variable>varAUTOCLOSE</variable>
							<label>'$(gettext 'Auto close output window on successful completion')'</label>
						</checkbox>

						<checkbox>
							<default>false</default>
							<variable>varLISTMODE</variable>
							<label>'$(gettext 'List contents instead of extracting')'</label>
							<action>if true disable:varAUTOCLOSE</action>
							<action>if true disable:varCHOOSER</action>
							<action>if false enable:varAUTOCLOSE</action>
							<action>if false enable:varCHOOSER</action>
						</checkbox>
					</vbox>

					<text space-fill="true" space-expand="true"><label>""</label></text>

					<vbox homogeneous="true" space-fill="false" space-expand="false">
						<hbox>
							<text space-fill="true" space-expand="true"><label>""</label></text>
							<hbox homogeneous="true" space-fill="true">
								<button ok>
									<action>echo "CHOOSER=\"$varCHOOSER\""</action>
									<action>echo "AUTOCLOSE=\"$varAUTOCLOSE\""</action>
									<action>echo "LISTMODE=\"$varLISTMODE\""</action>
									<action>closewindow:varCHOOSER</action>
								</button>
								<button cancel>
									<action>closewindow:varCHOOSER</action>
								</button>
							</hbox>
						</hbox>
					</vbox>

				</hbox>

			</vbox>

		</window>
		' | $GTKDIALOG -s)"

		CUSTOMDIR="$(echo "$CHOOSER" | grep '^CHOOSER=' | sed -n 's/.*="\(.*\)"/\1/p')"
		eval $(echo "$CHOOSER" | grep -E '^EXIT=|^AUTOCLOSE=|^LISTMODE=')
		if [ "$EXIT" = 'closewindow' ] && ([ "$CUSTOMDIR" ] || [ "$LISTMODE" ]); then
			return 0
		else
			return 1
		fi
	
	elif [ "$GUI" = 'yad' ]; then

		YAD_KEY=$(( ${RANDOM} * ( $$ % 32768 ) ))
		
		${YAD_BIN} --plug=${YAD_KEY} --tabnum=1 --file --directory > "${WORKDIR}/yad_file" &
		
		${YAD_BIN} --plug=${YAD_KEY} --tabnum=2 --form \
			--field "$(gettext "Auto close output window on successful comlpetion")":CHK TRUE \
			--field "$(gettext "List contents instead of extracting")":CHK FALSE > "${WORKDIR}/yad_chk" &
		
		${YAD_BIN} --title "$APPNAME" \
			--window-icon="${ICON}" \
			--width=$(hidpi_apply_scale 600) --height=$(hidpi_apply_scale 500) \
			--center --text-align=center \
			--text "<span size='"'x-large'"'><b>$(gettext "Select output directory")</b></span>" \
			--button gtk-info:'bash -c "f_show_dialog all"' \
			--button gtk-ok:0 \
			--button gtk-cancel:1 \
			--paned --key=${YAD_KEY} --orient=vert --splitter=360
		
		RETCODE=$?
		
		pkill -f "yad.*--(key|plug)=${YAD_KEY} "	# kill zombie processes, if any
		YAD_KEY=''
		
		CUSTOMDIR="$(cat "${WORKDIR}/yad_file")"
		CHECKBOXES="$(cat "${WORKDIR}/yad_chk")"
		CHECKBOXES="${CHECKBOXES%?}"
		AUTOCLOSE="$(echo "${CHECKBOXES%%|*}" | tr '[:upper:]' '[:lower:]')"
		LISTMODE="$(echo "${CHECKBOXES#*|}" | tr '[:upper:]' '[:lower:]')"
		
		[ $RETCODE -eq 0 ] && return 0 || return 1
		
	else
	
		CUSTOMDIR="$(Xdialog --stdout \
							 --center \
							 --title "$APPNAME" \
							 --backtitle "$(gettext 'Select output directory')" \
							 --check "$(gettext 'Auto close output window on successful completion')" on \
							 --dselect "${CURRENTDIR}" 0 0 2>/dev/null)"
		
		RETCODE=$?

		LISTMODE='false'
		AUTOCLOSE="$(echo "$CUSTOMDIR" | tail -n 1)"
		CUSTOMDIR="$(echo "$CUSTOMDIR" | head -n -1)"
		
		[ "$AUTOCLOSE" = 'checked' ] && AUTOCLOSE='true' || AUTOCLOSE='false'
		
		[ $RETCODE -eq 0 ] && return 0 || return 1
	
	fi

}

# =============================================================================

### START

case "$1" in

	--filetypes)
		f_show_dialog filetypes
		exit
		;;

	--backends)
		f_show_dialog backends
		exit
		;;

	--dependencies)
		f_show_dialog dependencies
		exit
		;;

	--weblinks)
		f_show_dialog weblinks
		exit
		;;

esac

# -----------------------------------------------------------------------------

IFILES=( "$@" )

if [ ${#IFILES[@]} -eq 0 ]; then
	while [ ! "$IFILES" ]; do
		f_input_files || exit 1
	done
fi

CURRENTDIR="${IFILES[0]%/*}/"
cd -- "$CURRENTDIR" || exit 1

f_output_dir || exit 1

# =============================================================================

export PS1="# "

[ "$LISTMODE" = 'true' ] && LM='-l' || LM=''

if [ "$GUI" != 'gtkdialog' ] || [ "$GTKDLG_VTE" != 'true' ] || [ ! -z "$UEXTRACT_TERM" ]; then

	echo '#! /bin/bash
trap "'"rm -rf $WORKDIR"'" EXIT
'${MYPATH}'/uextract "$@"
RETVAL=$?
rm -f '${TMPEXEC}'' > "$TMPEXEC"

	if [ "$AUTOCLOSE" = "true" ] && [ "$LISTMODE" != 'true' ]; then
		echo '[ $RETVAL -eq 0 ] && exit' >> "$TMPEXEC"
	fi

	echo '/bin/sh' >> "$TMPEXEC"

	chmod +x "$TMPEXEC"
	
	for i in $UEXTRACT_TERM $TERMINAL $TERM defaultterm x-terminal-emulator mate-terminal gnome-terminal konsole xfce4-terminal terminator lxterminal roxterm urxvt rxvt termit Eterm aterm uxterm termite sakura xterm vte terminology st qterminal lilyterm tilix terminix kitty alacritty hyper wezterm rio guake tilda; do
		type "$i" >/dev/null 2>&1 && { EXEC_TERMINAL="$i"; break; }
	done
	
	case "$EXEC_TERMINAL" in
		xfce4-terminal|mate-terminal)	EXEC_OPT='-x'	;;
		*)								EXEC_OPT='-e'	;;
	esac
	
	exec $EXEC_TERMINAL -T "$APPNAME" ${EXEC_OPT} ${TMPEXEC} ${LM} -r -o "$CUSTOMDIR" "${IFILES[@]}"
	
else
	
	echo "clear; trap 'rm -rf $WORKDIR' EXIT" > "$TMPEXEC"
	
	CUSTOMDIR="${CUSTOMDIR//\'/\'\"\'\"\'}"
	echo -n "${MYPATH}/uextract ${LM} -r -o '$CUSTOMDIR'" >> "$TMPEXEC"
	
	for FILE in $(seq 0 $((${#IFILES[@]}-1))); do
		IFILES[$FILE]="${IFILES[$FILE]//\'/\'\"\'\"\'}"
		echo -n " '${IFILES[$FILE]}'" >> "$TMPEXEC"
	done
	
	chmod +x "$TMPEXEC"
	
	export MAIN='
	<window title="'${APPNAME}'" image-name="'${ICON}'">
		<vbox>
			<terminal argv0="/bin/sh"
				scrollback-lines="100000"
				has-focus="true"
				text-background-color="#ffffff"
				text-foreground-color="#000000"
				vscrollbar-policy="0">
				<variable>vte0</variable>
				<width>83</width>
				'$(if [ "$AUTOCLOSE" = "true" ] && [ "$LISTMODE" != 'true' ]; then
					echo '<input>echo "HISTFILE=; printf \"\033c\";' ${TMPEXEC}' && exit"</input>'
				else
					echo '<input>echo "HISTFILE=; printf \"\033c\";' ${TMPEXEC}'"</input>'
				fi)'
				<action signal="child-exited">exit:EXIT</action>
			</terminal>
		</vbox>
	</window>'
	
	exec $GTKDIALOG -cp MAIN
fi

exit
