#!/bin/sh
set -e

# grub-mkconfig helper script.
# Copyright (C) 2010  Alexander Kurtz <kurtz.alex@googlemail.com>
# Copyright (C) 2019  Nikolai Kostrigin <nickel@altlinux.org>
#
# GRUB is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GRUB is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.

prefix=/usr
exec_prefix=/usr
bindir=/usr/bin
libdir=/usr/lib64
datadir=/usr/share

# Include the GRUB helper library for grub-mkconfig.
. ${datadir}/grub/grub-mkconfig_lib

# Set the location of a possibly necessary cache file for the background image.
# NOTE: This MUST BE A DOTFILE to avoid confusing it with user-defined images.
BACKGROUND_CACHE=".background_cache"

set_default_theme(){
	# Set a monochromatic theme as a last resort for unsuitable user choice.
	echo "${1}set menu_color_normal=white/black"
	echo "${1}set menu_color_highlight=black/light-gray"
}

set_user_colors (){
	# Don't set defaults if contrast color theme is already defined.
	# Even if no background is set.
	# This enables third-party customizers to pass their settings.
	local fgcolor=
	local bgcolor=
	if [ -n "${GRUB_COLOR_NORMAL}" ] && [ -n "${GRUB_COLOR_HIGHLIGHT}" ]; then
		fgcolor="$(echo ${GRUB_COLOR_NORMAL} |cut -d / -f 1)"
		bgcolor="$(echo ${GRUB_COLOR_NORMAL} |cut -d / -f 2)"

		# if foreground is in contrast to background then apply color scheme
		if [ "${fgcolor}" != "${bgcolor}" ]; then
			echo "${1}set menu_color_normal=${GRUB_COLOR_NORMAL}"
			echo "${1}set menu_color_highlight=${GRUB_COLOR_HIGHLIGHT}"
			echo "${1}set color_normal=${GRUB_COLOR_NORMAL}"
			echo "${1}set color_highlight=${GRUB_COLOR_HIGHLIGHT}"
		else
			set_default_theme "${1}"
		fi
	else
		set_default_theme "${1}"
	fi
}

module_available(){
	local module
	for module in "${1}.mod" */"${1}.mod"; do
		if [ -f "${module}" ]; then
			return 0
		fi
	done
	return 1
}

set_background_image(){
	# Step #1: Search all available output modes ...
	local output
	for output in ${GRUB_TERMINAL_OUTPUT}; do
		if [ "x$output" = "xgfxterm" ]; then
			break
		fi
	done

	# ... and check if we are able to display a background image at all.
	if ! [ "x${output}" = "xgfxterm" ]; then
		return 1
	fi

	# Step #2: Check if the specified background image exists.
	if ! [ -f "${1}" ]; then
		return 2
	fi

	# Step #3: Search the correct GRUB module for our background image.
	local reader
	case "${1}" in
		*.jpg|*.JPG|*.jpeg|*.JPEG) reader="jpeg";;
		*.png|*.PNG) reader="png";;
		*.tga|*.TGA) reader="tga";;
		*) return 3;; # Unknown image type.
	esac

	# Step #4: Check if the necessary GRUB module is available.
	if ! module_available "${reader}"; then
		return 4
	fi

	# Step #5: Check if GRUB can read the background image directly.
	# If so, we can remove the cache file (if any). Otherwise the backgound
	# image needs to be cached under /boot/grub.
	if is_path_readable_by_grub "${1}"; then
		rm --force "${BACKGROUND_CACHE}.jpeg" \
			"${BACKGROUND_CACHE}.png" "${BACKGROUND_CACHE}.tga"
	elif cp "${1}" "${BACKGROUND_CACHE}.${reader}"; then
		set -- "${BACKGROUND_CACHE}.${reader}" "${2}" "${3}"
	else
		return 5
	fi

	# Step #6: Prepare GRUB to read the background image.
	if ! prepare_grub_to_access_device "`${grub_probe} --target=device "${1}"`"; then
		return 6
	fi

	# Step #7: Everything went fine, print out a message to stderr ...
	gettext_printf "Found background image: %s\n" "${1}" >&2

	# ... and write our configuration snippet to stdout. Use the colors
	# desktop-base specified. If we're using a user-defined background, use
	# the default colors since we've got no idea how the image looks like.
	# If loading the background image fails, use the default theme.
	echo "insmod ${reader}"
	echo "if background_image -m stretch `make_system_path_relative_to_its_root "${1}"`; then"
	if [ -n "${2}" ]; then
		echo "  set color_normal=${2}"
	fi
	if [ -n "${3}" ]; then
		echo "  set color_highlight=${3}"
	fi
	if [ -z "${2}" ] && [ -z "${3}" ]; then
		echo "  true"
	fi
	echo "else"
	set_user_colors "  "
	echo "fi"
}

# We want to work in /boot/grub only to be able to check
# modules presence and store cached images if needed
test -d /boot/grub; cd /boot/grub

# Consider GRUB_WALLPAPER a deprecated parameter, but support it to avoid
# backward compatibility issues. Honor the priority of GRUB_BACKGROUND though
if [ -n "${GRUB_BACKGROUND}" ]; then
	set_background_image "${GRUB_BACKGROUND}" "${GRUB_COLOR_NORMAL}" "${GRUB_COLOR_HIGHLIGHT}" \
		&& exit 0
fi

# Next try to use the background image from GRUB_WALLPAPER.
if [ -n "${GRUB_WALLPAPER}" ]; then
	set_background_image "${GRUB_WALLPAPER}" "${GRUB_COLOR_NORMAL}" "${GRUB_COLOR_HIGHLIGHT}" \
		&& exit 0
fi

# Finally, if all of the above fails, use the pictureless color menu theme.
set_user_colors
