#!/bin/bash

export GUI=true
source Cruncher || exit 1
LOCATION="$(zenity --class=Cruncher --name="CruncherGui" --file-selection --directory --title="Select game folder")"
[ -d "$LOCATION" ] || exit 0
cd "$LOCATION"
: "${VPARALLEL=true}"  # applies if unset
: "${ERRORSONLY=true}" # applies if unset
parse-args "$@"

export PIPE_PID="$(mktemp -t Cruncher.XXX.pid)"
function pipe-pid  { bash -c 'echo $PPID' > "$PIPE_PID"; }
function pipe-kill { pkill -P "$(head -n1 "$PIPE_PID")"; echo -n > "$PIPE_PID"; return 1; }
function nocolor   { sed $'s/\e\\[[-0-9]*G/\t\t/g' | sed $'s/\e\\[[;0-9]*[a-zA-Z]//g'; }
function zenity+   { zenity "${DIALOG[@]}" "$@"; }
function -menu     { zenity+ --list --cancel-label="Back" "$@"; }
function -textinfo { zenity+ --text-info "$@" || pipe-kill; }
function -progress { zenity+ --progress --height=100 --time-remaining --percentage=0 --auto-kill "$@" || pipe-kill; }
function -report   { zenity+ --notification --text="Cruncher: Finished in $(show-time $TOTAL_TIME)"; }

function show-bool { $1 && echo yes || echo no; }

function gui-status {
	(pipe-pid && (
		splash
		PRETEND=true images
		PRETEND=true audio
		PRETEND=true video
		PRETEND=true report image audio video
		extra-info
		warning
		echo -e "\n  Press Enter to continue..."
	)) 2>&1 | -textinfo --ok-label="Proceed" --cancel-label="Quit"
}

function gui-menu {
	while true; do
		EXTRAS=( "" ""  i "Check/modify runtime parameters information" )
		[ "$MODE" = RenPy ] && EXTRAS=( "" ""  x "Extract *.rpa archives"    \
		                                       c "Repack *.rpa/ to archives"                   "${EXTRAS[@]}" )
		[ "$MODE" = RPGM  ] && EXTRAS=( "" ""  d "Decrypt MV resource files" \
		                                       D "Decrypt MV resource files (autodetect key)"  "${EXTRAS[@]}" )
		[ "$MODE" = Ace   ] && EXTRAS=( "" ""  r "Extract Game.rgss3a archive (irreversible)"  "${EXTRAS[@]}" )
		REPLY=$(-menu --text="Please select files to process:" --column="#" --column="Action" \
			1 "Image files"  2 "Audio files"  3 "Video files"  "" ""  6 "All of the above"  "${EXTRAS[@]}")
		[ $? = 0 ] || return
		[ "$REPLY" ] && echo "$REPLY" && break
	done
}

function gui-parameters {
	while true; do
		init >/dev/null
		DIALOG=( --class=Cruncher --name="CruncherGui" --title="${NAME} {$GAME}" --width=800 --height=600 )
		local PARALLEL REPLY RESULT IMG=WebP _THREADS="$THREADS" FVERSION="$(ffmpeg-version)"
		[ "$PARALLEL_" ] && PARALLEL=true || PARALLEL=false
		[ "$MODE" = Ace ] && IMG=JPEG
		[ "$THREADS" = 0 ] && _THREADS=auto
		REPLY=$(-menu --text="Choose parameter to modify" --column="Parameter" --column="Value" --column="Description" \
			GAMEDIR       " $GAMEDIR"                 "Folder to be scanned for updates" \
			MODE          " $MODE"                    "Game engine type (Ren'Py, RPG Maker MV/MZ/Ace, other)" \
			QUALITY       " $QUALITY"                 "[Image] resulting $IMG quality" \
			WMETHOD       " $WMETHOD"                 "[Image] WebP compression method" \
			OPACITY       " $(show-opacity $OPACITY)" "[Ace] PNG transparency threshold (for JPEG conversion)" \
			THREADS       " $_THREADS"                "[Audio/Video] ffmpeg threads number" \
			LOGLEVEL      " $LOGLEVEL"                "[Audio] ffmpeg loglevel settings (for terminal)" \
			[VLOGLEVEL]   " $VLOGLEVEL"               "[Video] ffmpeg loglevel settings (generated from LOGLEVEL & VPARALLEL)" \
			ERRORSONLY    " $(show-bool $ERRORSONLY)" "limit terminal output to errors only" \
			ACCEL         " $(show-bool $ACCEL)"      "[Video] ffmpeg VP9 GPU acceleration (affects compression/quality)" \
			PARALLEL      " $(show-bool $PARALLEL)"   "parallel processing (to affect videos, also enable VPARALLEL or ACCEL)" \
			VPARALLEL     " $(show-bool $VPARALLEL)"  "[Video] use parallel processing on videos" \
			""            ""                          "" \
			PARALLEL_     " $_PARALLEL"               "path to parallel executable" \
			FFMPEG        " $FFMPEG (v$FVERSION)"     "path to ffmpeg executable" \
			CONVERT       " $CONVERT"                 "path to imagemagick convert executable" \
			RPATOOL       " $RPATOOL"                 "path to rpatool script" \
			MVDECRYPTOR   " $MVDECRYPTOR"             "path to MvDecryptor script" \
			RGSSDECRYPTOR " $RGSSDECRYPTOR"           "path to RgssDecryptor script")
		[ $? = 0 ] || return
		case "$REPLY" in
		    GAMEDIR)
			RESULT="$(realpath "$GAMEDIR")/"
			RESULT="$(zenity --file-selection --directory --filename="$RESULT" --title="Locate game resources")"
			[ "$RESULT" ] && GAMEDIR="$(realpath --relative-to=. "$RESULT")"
			[[ "${GAMEDIR%%/*}" = @(.|..) ]] || GAMEDIR="./$GAMEDIR"
			;;
		    MODE)
			RESULT=$(-menu --text="Select mode [currently $MODE]" --column="Mode" --column="Description" \
				RenPy "game on Ren'Py engine (designed for Visual Novel genre, scripted in Python)" \
				RPGM  "RPG Maker MV/MZ (designed for JRPG games, scripted in JS)" \
				Ace   "RPG Maker VX Ace (older version, scripted in Ruby)" \
				HTML  "generic/fallback option (mostly works for HMTL/Electron games)")
			if [ "$RESULT" ]; then
				local DEFAULT=false
				case $MODE in
				    RenPy) [ "$GAMEDIR" = ./game ] && DEFAULT=true ;;
				    RPGM)  [ "$GAMEDIR" = ./www  ] && DEFAULT=true ;;
				    *)     [ "$GAMEDIR" = .      ] && DEFAULT=true ;;
				esac
				MODE=$RESULT
				$DEFAULT && case $MODE in
				    RenPy) GAMEDIR="./game" ;;
				    RPGM)  GAMEDIR="./www"  ;;
				    *)     GAMEDIR="."      ;;
				esac
			fi
			;;
		    QUALITY)
			RESULT="$(zenity+ --scale --text="$IMG compression quality" --min-value=75 --value=$QUALITY)"
			[ "$RESULT" ] && let QUALITY=RESULT
			;;
		    WMETHOD)
			RESULT="$(zenity+ --scale --text="WebP compression method" --min-value=0 --max-value=6 --value=$WMETHOD)"
			[ "$RESULT" ] && let WMETHOD=RESULT
			;;
		    OPACITY)
			let RESULT=(OPACITY+255)/256
			RESULT="$(zenity+ --scale --text="PNG opacity threshold [x256]" --max-value=256 --value=$RESULT)"
			[ "$RESULT" ] && let OPACITY=RESULT*256
			(( OPACITY > 65535 )) && OPACITY=65535
			;;
		    THREADS)
			RESULT="$(zenity+ --scale --text="ffmpeg threads [0 = auto]" --max-value=`nproc --all` --value=$THREADS)"
			[ "$RESULT" ] && let THREADS=RESULT
			;;
		    ERRORSONLY)
			$ERRORSONLY && ERRORSONLY=false || ERRORSONLY=true
			$ERRORSONLY && local _LOGLEVEL='fatal -nostats' || local _LOGLEVEL='warning -stats'
			LOGLEVEL="-hide_banner -loglevel $_LOGLEVEL"
			;;
		    LOGLEVEL)
			RESULT="$(zenity+ --entry --text="ffmpeg log-level parameters" --height=100 --entry-text="$LOGLEVEL")"
			[ $? = 0 ] && LOGLEVEL="$RESULT"
			;;
		    '[VLOGLEVEL]') echo "auto-generated from LOGLEVEL" ;;
		    PARALLEL)
			if ! $PARALLEL; then
				PARALLEL_="$_PARALLEL"
			else
				PARALLEL_=
				$VPARALLEL && [ "$THREADS" = 1 ] && THREADS=0
				VPARALLEL=false
			fi
			;;
		    VPARALLEL)
			$VPARALLEL && VPARALLEL=false || VPARALLEL=true
			$VPARALLEL   && [ "$THREADS" = 0 ] && THREADS=1
			! $VPARALLEL && [ "$THREADS" = 1 ] && THREADS=0
			$VPARALLEL && PARALLEL_="$_PARALLEL"
			;;
		    ACCEL)
			$ACCEL && ACCEL=false || ACCEL=true
			;;
		    PARALLEL_)
			local RESULT="$(zenity+ --file-selection --filename="$_PARALLEL" --title="Locate parallel")"
			if [ "$RESULT" ]; then
				_PARALLEL="$RESULT"
				[ "$PARALLEL_" ] && PARALLEL_="$_PARALLEL"
			fi
			;;
		    FFMPEG|CONVERT|RPATOOL|MVDECRYPTOR|RGSSDECRYPTOR)
			case "$REPLY" in
			    MVDECRYPTOR)   local NAME=MvDecryptor ;;
			    RGSSDECRYPTOR) local NAME=RgssDecryptor ;;
			    *)             local NAME=${REPLY,,} ;;
			esac
			local RESULT="$(zenity+ --file-selection --filename="${!REPLY}" --title="Locate $NAME")"
			[ "$RESULT" ] && declare $REPLY="$RESULT"
			;;
		    *) echo "$REPLY" ;;
		esac
	done
}

while true; do
	init
	DIALOG=( --class=Cruncher --name="CruncherGui" --title="${NAME} {$GAME}" --width=800 --height=600 )
	gui-status || break
	case "$(gui-menu)" in
		1) (pipe-pid && images && -report) | -progress --title="Crunching image files..." ;;
		2) (pipe-pid && audio  && -report) | -progress --title="Crunching audio files..." ;;
		3) (pipe-pid && video  && -report) | -progress --title="Crunching video files..." ;;
		6) (pipe-pid && images && audio && video && -report) | -progress --title="Crunching game resources..." ;;
		x) (pipe-pid && rpa unpack 2>&1) | -textinfo --auto-scroll ;;
		c) (pipe-pid && rpa repack 2>&1) | -textinfo --auto-scroll ;;
		d) (pipe-pid && "$MVDECRYPTOR" 2>&1) | -textinfo --auto-scroll ;;
		D) (pipe-pid && DETECT=yes "$MVDECRYPTOR" 2>&1) | -textinfo --auto-scroll ;;
		r) (pipe-pid && rgss-unpack 2>&1) | nocolor | -textinfo --auto-scroll ;;
		i) gui-parameters ;;
	esac
done
rm --force "$PIPE_PID"
