#!/bin/bash
SCRIPT="${BASH_SOURCE:-$0}"
SCRIPT_PATH="$(dirname "${SCRIPT}")"
source "${SCRIPT_PATH}/common.src"

# Grab current PID
LEADER_PID=$$

# Prefer the system utilities...
export PATH="${PATH}:${SCRIPT_PATH}/utils"

SWPFILE=~/.tmntswap

if ! command -v mono &> /dev/null
then
    msgbox "Error." $'The Mono Runtime could not be located.\nPlease install Mono and try again.'
    exit 1
fi

# Ask questions first...
if [[ ! -f "${gamedir}/gamedata/.patch_done" ]]; then
	confirm $'Precompile Game Code?' $'Pre-compile the game code for this device?\nPatching will take longer.'
	COMPILE=$RESULT
fi

if [[ ! -f "${gamedir}/gamedata/.astc_done" ]]; then
	confirm $'Use High Quality Compression?' $'Does not affect performance or load time.\nCompression will take longer.'
	HQ_COMPRESSION=$RESULT
fi

if [[ ! -f "${gamedir}/gamedata/.intro_done" ]]; then
	confirm $'Reencode Intro?' $'Re-encode the game\'s intro movie?\nThis might take 5 to 10 minutes.'
	ENC_INTRO=$RESULT
fi

trap "sig_usr31_trap" SIGUSR1
sig_usr31_trap() {
	# Abort everything.
	kill_recursive $$
	if [ -f $SWPFILE ]; then
		$ESUDO swapoff ${SWPFILE}
		$ESUDO rm ${SWPFILE}
	fi
	
	msgbox "Error." $'Fatal error performing first time setup.\nGame files left in a possibly broken state.'
	exit 1
}

# Patch the game's code to work around OpenGL deadlocks and other general
# compatibility issues
patch() {
	# MONOMODDED files not found, let's perform patching
	if [[ ! -f "${gamedir}/gamedata/.patch_done" ]]; then
		echo "First Time Setup: Applying game patches..."

		# Configure MonoMod settings
		export MONOMOD_MODS="$gamedir/patches"
		export MONOMOD_DEPDIRS="${MONO_PATH}":"${gamedir}/monomod"

		# Patch the ParisEngine/gameassembly files
		(
			set -e

			mono "${gamedir}/monomod/MonoMod.exe" "${gamedir}/gamedata/ParisEngine.dll"
			mono "${gamedir}/monomod/MonoMod.exe" "${gamedir}/gamedata/${gameassembly}"

			if [[ ${COMPILE} == 1 ]]; then
				mono --ffast-math -O=all --aot=llvm "${gamedir}/gamedata/MONOMODDED_ParisEngine.dll"
				mono --ffast-math -O=all --aot=llvm "${gamedir}/gamedata/MONOMODDED_${gameassembly}"
				
				# Move the precompiled bins so that Mono will find them
				mv "${gamedir}/gamedata/MONOMODDED_ParisEngine.dll.so" "${gamedir}/gamedata/ParisEngine.dll.so"
				mv "${gamedir}/gamedata/MONOMODDED_${gameassembly}.so" "${gamedir}/gamedata/${gameassembly}.so"
			fi
		)

		ERR=$?
		if [[ $ERR != 0 ]]; then
			rm -f "${gamedir}/gamedata/.patch_done"
			echo "Failure patching game binaries."
			kill -s SIGUSR1 $LEADER_PID
			exit 1
		fi

		# Regenerate sha1sum checks
		sha1sum "${gamedir}/gamedata/"{ParisEngine.dll,TMNT.exe} > "${gamedir}/gamedata/.ver_checksum"
		sha1sum "${gamedir}/patches/"*.dll >> "${gamedir}/gamedata/.ver_checksum"

		# Mark step as done
		touch "${gamedir}/gamedata/.patch_done"
	fi
}

# Re-encode game textures due to RAM constraints.
# You can change ASTC_QUALITY (goes from 0 to 100) to set the quality
# preset of the re-encoder. This only affects the quality of the final image
# and the time it takes to perform recompression, not performance.
astc() {
	if [[ ! -f "${gamedir}/gamedata/.astc_done" ]]; then
		export ASTC_QUALITY=10.0
		if [[ "${HQ_COMPRESSION}" == 1 ]]; then
			export ASTC_QUALITY=60.0
		fi

		mono "${gamedir}/FNARepacker.exe" "${gamedir}/gamedata/Content/"
		if [[ $? != 0 ]]; then
			rm -f "${gamedir}/gamedata/.astc_done"
			echo "Failure patching game binaries."
			kill -s SIGUSR1 $LEADER_PID
			exit 1
		fi

		# Mark step as done
		touch "${gamedir}/gamedata/.astc_done"
	fi
}

# Optionally encode the game's intro movie
intro() {
	if [[ "$ENC_INTRO" == 1 ]]; then
		ffmpeg \
			-y -hide_banner -loglevel error \
			-i Content/Videos/TMNT_GameIntro.ogv \
			-vf "scale=iw/2:ih/2" -c:v libtheora -q:v 5 -c:a copy \
			/tmp/PATCH_TMNT_GameIntro.ogv

		if [[ $? == 0 ]]; then
			mv /tmp/PATCH_TMNT_GameIntro.ogv Content/Videos/PATCH_TMNT_GameIntro.ogv
			touch "${gamedir}/gamedata/.intro_done"
		else
			echo "Warning, failure trying to re-encode game intro."
			rm -f /tmp/PATCH_TMNT_GameIntro.ogv
		fi
	else
		touch "${gamedir}/gamedata/.intro_done"
	fi
}

# Create swap for compile step...
if [[ ${COMPILE} == 1 ]]; then
	if [ -f $SWPFILE ]; then
		$ESUDO swapoff ${SWPFILE}
		$ESUDO rm ${SWPFILE}
	fi

	# This step might fail on 1GB devices, add swap if that's the case...
	mem_total=$(awk '/^MemTotal:/{print $2}' /proc/meminfo)
	if [[ $mem_total -lt 1816820 ]]; then
		echo "First Time Setup: Creating swap file..."

		$ESUDO dd if=/dev/zero of=${SWPFILE} bs=1M count=512
		$ESUDO chmod 600 ${SWPFILE}
		$ESUDO mkswap ${SWPFILE}
		$ESUDO swapon ${SWPFILE}
	fi
fi

# Perform some of the tasks in parallel by detaching the subshells
# To avoid too much resource pressure, we're only encoding the intro once
# the patching process has finished.

				 (patch) & pid_patch=$! # Patch game code
				  (astc) & pid_astc=$!  # Compress game textures
wait $pid_patch; (intro) & pid_intro=$! # Transcode game intro

# Wait for all processes to finish.
wait

# Created swap? now delete it.
if [ -f $SWPFILE ]; then
	$ESUDO swapoff ${SWPFILE}
	$ESUDO rm ${SWPFILE}
fi

exit 0
