# Keep compatibility with 2.32 and older

hacks_list() {
	local hacks_list
	hacks_list=$(context_value 'PRELOAD_HACKS_LIST')

	if [ -z "$hacks_list" ]; then
		return 0
	fi

	if compatibility_level_is_at_least '2.33'; then
		warning_deprecated_variable 'PRELOAD_HACKS_LIST' 'LD_PRELOAD_SOURCE'
	fi

	local hack
	for hack in $hacks_list; do
		printf '%s\n' "$hack"
	done
}

hack_name() {
	local hack
	hack="$1"

	local hack_name
	hack_name=$(context_value "${hack}_NAME")

	# Throw an error if the name is empty
	if [ -z "$hack_name" ]; then
		error_missing_variable "${hack}_NAME"
		return 1
	fi

	# Throw an error if the name includes line breaks
	local line_breaks_number
	line_breaks_number=$(printf '%s' "$hack_name" | wc --lines)
	if [ "$line_breaks_number" -gt 0 ]; then
		error_variable_multiline "${hack}_NAME"
		return 1
	fi

	printf '%s' "$hack_name"
}

hack_description() {
	local hack
	hack="$1"

	local hack_description
	hack_description=$(context_value "${hack}_DESCRIPTION")

	# Throw an error if the description is empty
	if [ -z "$hack_description" ]; then
		error_missing_variable "${hack}_DESCRIPTION"
		return 1
	fi

	printf '%s' "$hack_description"
}

hack_package() {
	local hack
	hack="$1"

	local hack_package
	hack_package=$(context_value "${hack}_PACKAGE")

	# Fall back on the current package identifier
	if [ -z "$hack_package" ]; then
		hack_package=$(current_package)
	fi

	printf '%s' "$hack_package"
}

hack_source() {
	local hack
	hack="$1"

	local hack_source
	hack_source=$(context_value "${hack}_SOURCE")

	# Throw an error if the source is empty
	if [ -z "$hack_source" ]; then
		error_missing_variable "${hack}_SOURCE"
		return 1
	fi

	printf '%s' "$hack_source"
}

hack_build() {
	local hack
	hack="$1"

	# Write the source file
	local hack_path_source
	hack_path_source=$(hack_path_source "$hack")
	mkdir --parents "${PLAYIT_WORKDIR}/hacks"
	hack_source "$hack" > "$hack_path_source"

	# Prepare the compiler options string
	local gcc_options
	gcc_options='-shared -Wall -fPIC -ldl'
	local hack_package hack_package_architecture
	hack_package=$(hack_package "$hack")
	hack_package_architecture=$(package_architecture "$hack_package")
	if [ "$hack_package_architecture" = '32' ]; then
		gcc_options="$gcc_options -m32"
	fi

	# Build the .so library
	local hack_path_library hack_build_status
	hack_path_library=$(hack_path_library "$hack")
	{
		gcc $gcc_options "$hack_path_source" -o "$hack_path_library"
		hack_build_status=$?
	} || true
	if [ "$hack_build_status" -ne 0 ]; then
		error_hack_build_failure
		return 1
	fi
	rm "$hack_path_source"
}

hack_path_source() {
	local hack
	hack="$1"

	local hack_name
	hack_name=$(hack_name "$hack")

	printf '%s/hacks/%s.c' "$PLAYIT_WORKDIR" "$hack_name"
}

hack_path_library() {
	local hack
	hack="$1"

	local hack_name
	hack_name=$(hack_name "$hack")

	printf '%s/hacks/%s.so' "$PLAYIT_WORKDIR" "$hack_name"
}

hacks_inclusion_default() {
	local packages_list package hacks_list hack
	packages_list=$(packages_list)
	for package in $packages_list; do
		hacks_list=$(hacks_included_in_package "$package")
		if [ -z "$hacks_list" ]; then
			continue
		fi
		for hack in $hacks_list; do
			hack_build "$hack"
			(
				set_current_package "$package"
				hack_inclusion "$hack"
			)
		done
	done
}

hack_inclusion() {
	local hack
	hack="$1"

	local hack_path_library
	hack_path_library=$(hack_path_library "$hack")
	if [ ! -f "$hack_path_library" ]; then
		return 1
	fi

	local hack_package hack_package_path path_libraries
	hack_package=$(hack_package "$hack")
	hack_package_path=$(package_path "$hack_package")
	path_libraries=$(path_libraries)
	install -D --mode=644 --target-directory="${hack_package_path}${path_libraries}/preload-hacks" "$hack_path_library"
	rm "$hack_path_library"
}

hack_application_prerun() {
	local hack
	hack="$1"

	local hack_description hack_description_line
	hack_description=$(hack_description "$hack")
	while read -r hack_description_line; do
		cat <<- EOF
		# $hack_description_line
		EOF
	done <<- EOL
	$(printf '%s' "$hack_description")
	EOL

	local hack_name path_libraries
	hack_name=$(hack_name "$hack")
	path_libraries=$(path_libraries)
	cat <<- EOF
	export LD_PRELOAD="\${LD_PRELOAD}:${path_libraries}/preload-hacks/${hack_name}.so"
	EOF
}

hacks_included_in_package() {
	local package
	package="$1"

	local hacks_list hack hack_package
	hacks_list=$(hacks_list)
	for hack in $hacks_list; do
		hack_package=$(hack_package "$hack")
		if [ "$hack_package" = "$package" ]; then
			printf '%s\n' "$hack"
		fi
	done
}

prefix_generate_links_farm() {
	if compatibility_level_is_at_least '3.33'; then
		warning_deprecated_function 'prefix_generate_links_farm' 'prefix_symlinks_generate'
	fi

	prefix_symlinks_generate
}

launcher_prefix_symlinks_build() {
	if compatibility_level_is_at_least '3.33'; then
		warning_deprecated_function 'launcher_prefix_symlinks_build' 'prefix_symlinks_generate'
	fi

	# This compatibility wrapper does nothing, as it is always called alongside prefix_generate_links_farm.
}

dependencies_list_native_libraries() {
	if compatibility_level_is_at_least '2.32'; then
		warning_deprecated_function 'dependencies_list_native_libraries' 'dependencies_libraries_list'
	fi

	dependencies_libraries_list "$@"
}

