# Print the id of the given package.
# USAGE: package_id $package
package_id() {
	local package
	package="$1"

	local package_id
	package_id=$(context_value "${package}_ID")
	## TODO: An alternative way to set the package id should be proposed, PKG_xxx_SUFFIX,
	##       with the complete id being computed from GAME_ID + PKG_xxx_SUFFIX.

	# Try to find a fallback value based on the package identifier:
	# current package → fallback package
	# PKG_BIN64       → PKG_BIN
	# PKG_BIN32       → PKG_BIN
	# PKG_LIBS64      → PKG_LIBS
	# PKG_LIBS32      → PKG_LIBS
	if [ -z "$package_id" ]; then
		case "$package" in
			('PKG_BIN64'|'PKG_BIN32')
				## Errors due to the later set_current_package call are ignored.
				package_id=$(package_id 'PKG_BIN' 2>/dev/null || true)
			;;
			('PKG_LIBS64'|'PKG_LIBS32')
				package_id=$(package_id 'PKG_LIBS')
			;;
		esac
	fi

	# Fall back on a default value for expansion parent packages.
	if [ -z "$package_id" ]; then
		local expansion_id
		expansion_id=$(expansion_id)
		if [ -n "$expansion_id" ]; then
			if [ "$package" = 'PKG_PARENT' ]; then
				## TODO: Check if setting the package context here is actually required,
				##       it’s doubtful expansion scripts would rely on package-specific GAME_ID.
				package_id=$(
					set_current_package "$package"
					game_id
				)
			fi
		fi
	fi

	# Fall back on the default package id for the current game engine
	if [ -z "$package_id" ]; then
		local game_engine
		game_engine=$(game_engine)
		case "$game_engine" in
			('gamemaker')
				package_id=$(package_id_gamemaker "$package")
			;;
			('visionaire')
				package_id=$(visionaire_package_id "$package")
			;;
		esac
	fi

	# Fall back on the game id if no package id is explicitly set
	if [ -z "$package_id" ]; then
		package_id=$(
			set_current_package "$package"
			game_id
		)
		## Include the expansion id if one is available.
		if [ -n "$expansion_id" ]; then
			package_id="${package_id}-${expansion_id}"
		fi
	fi

	# Check that the id fits the format restrictions.
	if ! printf '%s' "$package_id" |
		grep --quiet --regexp='^[0-9a-z][-0-9a-z]\+[0-9a-z]$'
	then
		error_package_id_invalid "$package_id"
		return 1
	fi

	# Apply tweaks specific to the target package format.
	local option_package
	option_package=$(option_value 'package')
	case "$option_package" in
		('arch')
			package_id=$(archlinux_package_id "$package_id")
		;;
		('gentoo')
			package_id=$(gentoo_package_id "$package_id")
		;;
	esac

	printf '%s' "$package_id"
}

# Print the architecture of the given package
# USAGE: package_architecture $package
# RETURNS: the package architecture, as one of the following values:
#          - 32
#          - 64
#          - all
package_architecture() {
	local package
	package="$1"

	local package_architecture
	package_architecture=$(context_value "${package}_ARCH")

	# If no architecture is explictly set for the given package, fall back to "all".
	if [ -z "$package_architecture" ]; then
		package_architecture='all'
	fi

	printf '%s' "$package_architecture"
}

# Print the desciption of the given package
# USAGE: package_description $package
# RETURNS: the package description, a non-empty string that should not include line breaks
package_description() {
	local package
	package="$1"

	local package_description
	package_description=$(context_value "${package}_DESCRIPTION")

	# Try to find a fallback value based on the package identifier:
	# current package → fallback package
	# PKG_LIBS64      → PKG_LIBS
	# PKG_LIBS32      → PKG_LIBS
	if [ -z "$package_description" ]; then
		case "$package" in
			('PKG_LIBS64'|'PKG_LIBS32')
				package_id=$(package_description 'PKG_LIBS')
			;;
		esac
	fi

	# Fall back on the default package description for the current game engine
	if [ -z "$package_description" ]; then
		local game_engine
		game_engine=$(game_engine)
		case "$game_engine" in
			('gamemaker')
				package_description=$(package_description_gamemaker "$package")
			;;
			('visionaire')
				package_description=$(visionaire_package_description "$package")
			;;
		esac
	fi

	# Check that the package description does not span multiple lines
	if [ "$(printf '%s' "$package_description" | wc --lines)" -gt 0 ]; then
		error_variable_multiline "${package}_DESCRIPTION"
		return 1
	fi

	printf '%s' "$package_description"
}

# Print the list of package names provided by the given package
# This list is used to ensure conflicting packages can not be installed at the same time.
# USAGE: package_provides $package
# RETURN: a list of provided package names,
#         one per line,
#         or an empty string
package_provides() {
	local package
	package="$1"

	local package_provides
	package_provides=$(context_value "${package}_PROVIDES")

	# Try to find a fallback value based on the package identifier:
	# current package → fallback package
	# PKG_BIN64       → PKG_BIN
	# PKG_BIN32       → PKG_BIN
	# PKG_LIBS64      → PKG_LIBS
	# PKG_LIBS32      → PKG_LIBS
	# PKG_L10N_??     → PKG_L10N
	if [ -z "$package_provides" ]; then
		case "$package" in
			('PKG_BIN64'|'PKG_BIN32')
				package_provides=$(package_provides 'PKG_BIN')
			;;
			('PKG_LIBS64'|'PKG_LIBS32')
				package_provides=$(package_provides 'PKG_LIBS')
			;;
			('PKG_L10N_'??)
				package_provides=$(package_provides 'PKG_L10N')
			;;
		esac
	fi

	# Return early if there is no package name to print
	if [ -z "$package_provides" ]; then
		return 0
	fi

	printf '%s' "$package_provides" | list_clean
}

# Print the actions that should be run post-installation for the given package
# USAGE: package_postinst_actions $package
# RETURN: a list of actions, that can span over several lines,
#         the list can be empty
package_postinst_actions() {
	local package
	package="$1"

	local postinst_actions
	postinst_actions=$(get_value "${package}_POSTINST_RUN")

	# Return early if no action is set.
	if [ -z "$postinst_actions" ]; then
		return 0
	fi

	# Ensure the list of actions always end with a line break.
	printf '%s\n' "$postinst_actions"
}

# Print the actions that should be run pre-removal for the given package
# USAGE: package_prerm_actions $package
# RETURN: a list of actions, that can span over several lines,
#         the list can be empty
package_prerm_actions() {
	local package
	package="$1"

	local prerm_actions
	prerm_actions=$(get_value "${package}_PRERM_RUN")

	# Return early if no action is set.
	if [ -z "$prerm_actions" ]; then
		return 0
	fi

	# Ensure the list of actions always end with a line break.
	printf '%s\n' "$prerm_actions"
}

# Print the warning messages that should be displayed at the end of the given package installation
# USAGE: package_postinst_warnings $package
# RETURN: one or several messages, separated by line breaks,
#         the message can be empty
package_postinst_warnings() {
	local package
	package="$1"

	get_value "${package}_POSTINST_WARNINGS"
}

