# Gentoo ("gentoo" variant) - Write the metadata for the listed packages
# USAGE: gentoo_packages_metadata $package[…]
gentoo_packages_metadata() {
	local package
	for package in "$@"; do
		gentoo_package_metadata_single "$package"
	done
}

# Gentoo ("gentoo" variant) - Write the metadata for the given package
# USAGE: gentoo_package_metadata_single $package
gentoo_package_metadata_single() {
	local package
	package="$1"

	local package_id package_name package_path package_prep_path
	package_id=$(package_id "$package")
	package_name=$(package_name "$package")
	package_path=$(package_path "$package")
	package_prep_path="$(realpath --canonicalize-existing "${package_path}/..")"
	mkdir --parents "$package_path"
	mkdir --parents "${package_prep_path}/metadata"
	touch "${package_prep_path}/gpkg-1"

	# The CHOST field can be used to limit installation to some triples,
	# but it can be omitted from the metadata with no issues.
	gentoo_field_rdepend "$package" > "${package_prep_path}/metadata/RDEPEND"
	printf '%s' "x-gentoo-overlay" > "${package_prep_path}/metadata/repository"
	printf '%s' "8" > "${package_prep_path}/metadata/EAPI"
	gentoo_field_description "$package" > "${package_prep_path}/metadata/DESCRIPTION"
	gentoo_field_keywords "$package" > "${package_prep_path}/metadata/KEYWORDS"
	printf '%s' "0" > "${package_prep_path}/metadata/SLOT"
	printf '%s' "${package_name%.gpkg.tar}" > "${package_prep_path}/metadata/PF"
	printf '%s' "games-playit" > "${package_prep_path}/metadata/CATEGORY"
	(gentoo_script_postinst "$package"; gentoo_script_prerm "$package") | bzip2 > "${package_prep_path}/metadata/environment.bz2"
	truncate --size=0 "${package_prep_path}/metadata/${package_name%.gpkg.tar}.ebuild"
}

# Gentoo ("gentoo" variant) - Build a list of packages
# USAGE: gentoo_packages_build $package[…]
gentoo_packages_build() {
	local package
	for package in "$@"; do
		gentoo_package_build_single "$package"
	done
}

# Gentoo ("gentoo" variant) - Build a single package
# USAGE: gentoo_package_build_single $package
gentoo_package_build_single() {
	local package
	package="$1"

	local package_path package_prep_path
	package_path=$(package_path "$package")
	package_prep_path="$(realpath --canonicalize-existing "${package_path}/..")"

	# Set the path where the package should be generated.
	local option_output_dir package_name generated_package_path
	option_output_dir=$(option_value 'output-dir')
	package_name=$(package_name "$package")
	generated_package_path="${option_output_dir}/${package_name}"

	# Skip packages already existing,
	# unless called with --overwrite.
	local option_overwrite
	option_overwrite=$(option_value 'overwrite')
	if
		[ "$option_overwrite" -eq 0 ] &&
		[ -e "$generated_package_path" ]
	then
		information_package_already_exists "$package_name"
		return 0
	fi

	# Set basic tar options.
	local tar_version tar_options
	tar_version=$(tar --version | head --lines 1)
	case "$tar_version" in
		(*'GNU tar'*)
			tar_options='--create --group=root --owner=root'
		;;
		(*'libarchive'*)
			tar_options='--create --gname=root --uname=root'
		;;
		(*)
			error_unknown_tar_implementation
			return 1
		;;
	esac

	# Set compression setting
	local option_compression tar_compress_program compression_suffix
	# For compression suffixes, see
	# https://www.gentoo.org/glep/glep-0074.html#compressed-file-formats
	option_compression=$(option_value 'compression')
	case "$option_compression" in
		('none')
			tar_compress_program=''
			compression_suffix=''
		;;
		('speed')
			tar_compress_program='gzip'
			compression_suffix='.gz'
		;;
		('size')
			tar_compress_program='xz'
			tar_compress_program='.xz'
		;;
	esac

	# Run the actual package generation, using tar
	## I think it only has to be approximate, I’m not even sure if it’s used or not
	printf '%s' "$(( $(du --apparent-size --block-size=1 --summarize | cut --fields=1)*2 ))" > "${package_prep_path}/metadata/SIZE"
	## Create image tar
	if [ -n "$tar_compress_program" ]; then
		env --chdir="$package_prep_path" tar $tar_options --use-compress-program="$tar_compress_program" --file "image.tar${compression_suffix}" image
	else
		env --chdir="$package_prep_path" tar $tar_options --file "image.tar${compression_suffix}" image
	fi
	rm --recursive "${package_prep_path}/image"
	## Create metadata tar
	if ! (
		cd "$package_prep_path"
		if [ -n "$tar_compress_program" ]; then
			tar $tar_options --use-compress-program="$tar_compress_program" --file "metadata.tar${compression_suffix}" metadata/*
		else
			tar $tar_options --file "metadata.tar${compression_suffix}" metadata/*
		fi
	)
	then
		error_package_generation_failed "$package_name"
		return 1
	fi
	rm --recursive "${package_prep_path}/metadata"
	## Create Manifest
	truncate --size=0 "${package_prep_path}/Manifest"
	for file in gpkg-1 "metadata.tar${compression_suffix}" "image.tar${compression_suffix}"; do
		local path="${package_prep_path}/${file}"
		#printf 'DATA %s %d SHA512 %s\n' >> "${package_prep_path}/Manifest" "$file" "$(stat --format='%s' "$path")" "$(sha512sum "$path" | cut --delimiter=' ' --fields=1)"
		printf 'DATA %s %d SHA512 %s BLAKE2B %s\n' >> "${package_prep_path}/Manifest" "$file" "$(stat --format='%s' "$path")" "$(sha512sum "$path" | cut --delimiter=' ' --fields=1)" "$(b2sum "$path" | cut --delimiter=' ' --fields=1)"
	done
	## Create combined package
	local package_prep_path_parent package_prep_path_name
	package_prep_path_parent=$(dirname "$package_prep_path")
	package_prep_path_name=$(basename "$package_prep_path")
	env --chdir="$package_prep_path_parent" tar $tar_options --file "$generated_package_path" "${package_prep_path_name}/gpkg-1" "${package_prep_path_name}/metadata.tar${compression_suffix}" "${package_prep_path_name}/image.tar${compression_suffix}" "${package_prep_path_name}/Manifest"
}

# Print the file name of the given package
# USAGE: package_name_gentoo $package
# RETURNS: the file name, as a string
package_name_gentoo() {
	local package
	package="$1"

	local package_id package_version package_name
	package_id=$(package_id "$package")
	package_version=$(package_version)
	package_name="${package_id}-${package_version}.gpkg.tar"

	# Avoid paths collisions when building multiple architecture variants for a same package
	local packages_list current_package current_package_id
	packages_list=$(packages_list)
	for current_package in $packages_list; do
		current_package_id=$(package_id "$current_package")
		if
			[ "$current_package" != "$package" ] &&
			[ "$current_package_id" = "$package_id" ]
		then
			local package_architecture
			package_architecture=$(gentoo_package_architecture_string "$package")
			package_name="${package_architecture}/${package_name}"
			break
		fi
	done

	printf '%s' "$package_name"
}

# Get the path to the directory where the given package image is prepared,
# relative to the directory where all packages are stored
# USAGE: package_path_gentoo $package
# RETURNS: relative path to a directory, as a string
package_path_gentoo() {
	local package
	package="$1"

	local package_name package_path
	package_name=$(package_name "$package")
	package_path="${package_name%.gpkg.tar}"

	printf '%s/image' "$package_path"
}

# Tweak the given package version string to ensure it is compatible with portage
# USAGE: gentoo_package_version $package_version
# RETURNS: the package version, as a non-empty string
gentoo_package_version() {
	local package_version
	package_version="$1"

	set +o errexit
	package_version=$(
		printf '%s' "$package_version" |
			grep --extended-regexp --only-matching '^([0-9]{1,18})(\.[0-9]{1,18})*[a-z]?'
	)
	set -o errexit

	if [ -z "$package_version" ]; then
		package_version='1.0'
	fi

	local script_version_string
	script_version_string=$(script_version)

	printf '%s_p%s' "$package_version" "$(printf '%s' "$script_version_string" | sed 's/\.//g')"
}

# Print the architecture string of the given package, in the format expected by portage
# USAGE: gentoo_package_architecture_string $package
# RETURNS: the package architecture, as one of the following values:
#          - x86
#          - amd64
#          - data (dummy value)
gentoo_package_architecture_string() {
	local package
	package="$1"

	local package_architecture package_architecture_string
	package_architecture=$(package_architecture "$package")
	case "$package_architecture" in
		('32')
			package_architecture_string='x86'
		;;
		('64')
			package_architecture_string='amd64'
		;;
		('all')
			# We could put anything here, it should not be used for package metadata.
			package_architecture_string='data'
		;;
	esac

	printf '%s' "$package_architecture_string"
}

# Tweak the given package id to ensure compatibility with portage
# USAGE: gentoo_package_id $package_id
# RETURNS: the package id, as a non-empty string
gentoo_package_id() {
	local package_id
	package_id="$1"

	# Avoid mixups between numbers in package id and version number.
	printf '%s' "$package_id" | sed 's/-/_/g'
}

