#!/bin/sh
set -o nounset

oneTimeSetUp() {
	# Load the ./play.it library
	. lib/libplayit2.sh
	# Set required options
	PLAYIT_OPTION_FREE_SPACE_CHECK=0
	PLAYIT_OPTION_PACKAGE='deb'
	PLAYIT_OPTION_PREFIX='/usr'
	script_version='19700101.1'
}

setUp() {
	# Set a temporary directory to mess with real files
	TEST_TEMP_DIR=$(mktemp --directory)
	export TEST_TEMP_DIR
}

tearDown() {
	rm --force --recursive "$TEST_TEMP_DIR"
}

test_applications_list() {
	local APPLICATIONS_LIST APP_MAIN_EXE APP_MAIN_EXE_SOME_CONTEXT APP_EXTRA_SCUMMID UNITY3D_NAME applications_list applications_list_expected

	applications_list=$(applications_list)
	assertNull "$applications_list"

	APPLICATIONS_LIST='APP_MAIN APP_CONFIG APP_EDITOR'
	applications_list=$(applications_list)
	applications_list_expected='APP_CONFIG
APP_EDITOR
APP_MAIN'
	assertEquals "$applications_list_expected" "$applications_list"
	unset APPLICATIONS_LIST

	APP_MAIN_EXE='something.x86_64'
	APP_EXTRA_SCUMMID='engine:game'
	applications_list=$(applications_list)
	applications_list_expected='APP_EXTRA
APP_MAIN'
	assertEquals "$applications_list_expected" "$applications_list"
	unset APP_MAIN_EXE APP_EXTRA_SCUMMID

	APP_MAIN_EXE_SOME_CONTEXT='something.x86_64'
	applications_list=$(applications_list)
	assertEquals 'APP_MAIN' "$applications_list"
	unset APP_MAIN_EXE_SOME_CONTEXT

	UNITY3D_NAME='SomeName'
	applications_list=$(applications_list)
	assertEquals 'APP_MAIN' "$applications_list"
}

test_application_prefix_type() {
	local application_prefix_type APP_MAIN_PREFIX_TYPE APPLICATIONS_PREFIX_TYPE APP_MAIN_TYPE

	APP_MAIN_PREFIX_TYPE='none'
	application_prefix_type=$(application_prefix_type 'APP_MAIN')
	assertEquals 'none' "$application_prefix_type"
	unset APP_MAIN_PREFIX_TYPE

	APPLICATIONS_PREFIX_TYPE='symlinks'
	application_prefix_type=$(application_prefix_type 'APP_MAIN')
	assertEquals 'symlinks' "$application_prefix_type"
	unset APPLICATIONS_PREFIX_TYPE

	APP_MAIN_TYPE='scummvm'
	application_prefix_type=$(application_prefix_type 'APP_MAIN')
	assertEquals 'none' "$application_prefix_type"
	APP_MAIN_TYPE='native'
	application_prefix_type=$(application_prefix_type 'APP_MAIN')
	assertEquals 'symlinks' "$application_prefix_type"
	unset APP_MAIN_TYPE

	# Invalid values should throw an error.
	APP_MAIN_PREFIX_TYPE='invalid'
	assertFalse 'application_prefix_type "APP_MAIN"'
}

test_application_id() {
	local GAME_ID APP_MAIN_ID application_id

	GAME_ID='some-game'
	application_id=$(application_id 'APP_MAIN')
	assertEquals 'some-game' "$application_id"

	APP_MAIN_ID='some-application'
	application_id=$(application_id 'APP_MAIN')
	assertEquals 'some-application' "$application_id"

	# Check the format restriction
	APP_MAIN_ID='-some-invalid-application-id'
	assertFalse 'application_id "APP_MAIN"'
}

test_application_exe() {
	local APP_MAIN_EXE UNITY3D_NAME application_exe

	unity3d_application_exe_default() {
		printf 'SomeGame.x86_64'
	}
	UNITY3D_NAME='SomeGame'
	application_exe=$(application_exe 'APP_MAIN')
	assertEquals 'SomeGame.x86_64' "$application_exe"

	APP_MAIN_EXE='SomeGame.exe'
	application_exe=$(application_exe 'APP_MAIN')
	assertEquals 'SomeGame.exe' "$application_exe"
}

test_application_exe_escaped() {
	local APP_MAIN_EXE application_exe_escaped

	APP_MAIN_EXE="Some'Tricky'Name.x86"
	application_exe_escaped=$(application_exe_escaped 'APP_MAIN')
	assertEquals "Some'\''Tricky'\''Name.x86" "$application_exe_escaped"
}

test_application_exe_path() {
	local \
		PLAYIT_OPTION_TMPDIR GAME_ID CONTENT_PATH_DEFAULT APP_MAIN_EXE \
		PACKAGES_LIST PKG_BIN32_ID PKG_BIN64_ID PKG_DATA_ID \
		PLAYIT_WORKDIR \
		application_exe_path_gamedata application_exe_path_bin32 application_exe_path_bin64 application_exe_path_data \
		PLAYIT_CONTEXT_PACKAGE_DEFAULT PLAYIT_CONTEXT_PACKAGE

	# Create a couple files in the temporary directory, and set required variables.
	PLAYIT_OPTION_TMPDIR="$TEST_TEMP_DIR"
	GAME_ID='some-game'
	CONTENT_PATH_DEFAULT='.'
	APP_MAIN_EXE='SomeGame.exe'
	PACKAGES_LIST='
	PKG_BIN32
	PKG_BIN64
	PKG_DATA'
	PKG_BIN32_ID='some-game-bin32'
	PKG_BIN64_ID='some-game-bin64'
	PKG_DATA_ID='some-game-data'
	set_default_package 'PKG_BIN32'
	init_working_directory
	application_exe_path_gamedata="${PLAYIT_WORKDIR}/gamedata/${CONTENT_PATH_DEFAULT}/${APP_MAIN_EXE}"
	application_exe_path_bin32="${PLAYIT_WORKDIR}/packages/${PKG_BIN32_ID}_1.0-1+19700101.1_all/usr/share/games/${GAME_ID}/${APP_MAIN_EXE}"
	application_exe_path_bin64="${PLAYIT_WORKDIR}/packages/${PKG_BIN64_ID}_1.0-1+19700101.1_all/usr/share/games/${GAME_ID}/${APP_MAIN_EXE}"
	application_exe_path_data="${PLAYIT_WORKDIR}/packages/${PKG_DATA_ID}_1.0-1+19700101.1_all/usr/share/games/${GAME_ID}/${APP_MAIN_EXE}"
	mkdir --parents \
		"$(dirname "$application_exe_path_gamedata")" \
		"$(dirname "$application_exe_path_bin32")" \
		"$(dirname "$application_exe_path_bin64")" \
		"$(dirname "$application_exe_path_data")"
	touch \
		"$application_exe_path_gamedata" \
		"$application_exe_path_bin32" \
		"$application_exe_path_bin64" \
		"$application_exe_path_data"

	# Look in the current package
	set_current_package 'PKG_BIN64'
	assertEquals "$application_exe_path_bin64" "$(application_exe_path "$APP_MAIN_EXE")"
	rm "$application_exe_path_bin32" "$application_exe_path_bin64"

	# Look in all packages
	assertEquals "$application_exe_path_data" "$(application_exe_path "$APP_MAIN_EXE")"
	rm "$application_exe_path_data"

	# Look in archive contents
	assertEquals "$application_exe_path_gamedata" "$(application_exe_path "$APP_MAIN_EXE")"
	rm "$application_exe_path_gamedata"
}

test_application_name() {
	local GAME_NAME APP_MAIN_NAME application_name

	GAME_NAME='Some Game'
	application_name=$(application_name 'APP_MAIN')
	assertEquals 'Some Game' "$application_name"

	APP_MAIN_NAME='Some Application'
	application_name=$(application_name 'APP_MAIN')
	assertEquals 'Some Application' "$application_name"
}

test_application_category() {
	local APP_MAIN_CAT application_category

	application_category=$(application_category 'APP_MAIN')
	assertEquals 'Game' "$application_category"

	APP_MAIN_CAT='Settings'
	application_category=$(application_category 'APP_MAIN')
	assertEquals 'Settings' "$application_category"
}

test_application_prerun() {
	local \
		application_prerun application_prerun_expected \
		APP_MAIN_PRERUN \
		PLAYIT_COMPATIBILITY_LEVEL APP_MAIN_TYPE \
		HACK_SDL1COMPAT_NAME HACK_SDL1COMPAT_DESCRIPTION HACK_NOATIME_NAME HACK_NOATIME_DESCRIPTION

	APP_MAIN_PRERUN='some commands'
	application_prerun=$(application_prerun 'APP_MAIN')
	assertEquals 'some commands' "$application_prerun"

	# Check that LD_PRELOAD hacks are automatically added
	hacks_included_in_package() {
		printf '%s\n' 'HACK_SDL1COMPAT' 'HACK_NOATIME'
	}
	path_libraries() {
		printf '/usr/lib/games/some-game'
	}
	HACK_SDL1COMPAT_NAME='smacshim'
	HACK_SDL1COMPAT_DESCRIPTION='LD_PRELOAD shim allowing the old engine to run on top of latest SDL1 library
cf. https://github.com/ZeroPointEnergy/smacshim'
	HACK_NOATIME_NAME='vv_noatime'
	HACK_NOATIME_DESCRIPTION='LD_PRELOAD shim working around the engine expectation that files are owned by the current user'
	application_prerun=$(application_prerun 'APP_MAIN')
	application_prerun_expected='some commands
# LD_PRELOAD shim allowing the old engine to run on top of latest SDL1 library
# cf. https://github.com/ZeroPointEnergy/smacshim
export LD_PRELOAD="${LD_PRELOAD}:/usr/lib/games/some-game/preload-hacks/smacshim.so"
# LD_PRELOAD shim working around the engine expectation that files are owned by the current user
export LD_PRELOAD="${LD_PRELOAD}:/usr/lib/games/some-game/preload-hacks/vv_noatime.so"'
	assertEquals "$application_prerun_expected" "$application_prerun"
}

test_application_postrun() {
	local APP_MAIN_POSTRUN APP_MAIN_TYPE PLAYIT_COMPATIBILITY_LEVEL application_postrun

	APP_MAIN_TYPE='native'
	APP_MAIN_POSTRUN='some commands'
	application_postrun=$(application_postrun 'APP_MAIN')
	assertEquals 'some commands' "$application_postrun"
}

test_application_options() {
	local APP_MAIN_OPTIONS application_options

	application_options=$(application_options 'APP_MAIN')
	assertNull "$application_options"

	APP_MAIN_OPTIONS='--some-option --some-other-option'
	application_options=$(application_options 'APP_MAIN')
	assertEquals '--some-option --some-other-option' "$application_options"

	# Ensure that line breaks are not allowed
	APP_MAIN_OPTIONS='--some-option
--some-other-option'
	assertFalse 'application_options failed to correctly prevent a multi-lines options string.' 'application_options "APP_MAIN"'

	return 0
}
