#!/bin/bash
# Run garuda hooks related commands.

# shellcheck source=/dev/null
source /usr/lib/garuda/garuda.shlib

Filesystem() {
	local file=/usr/lib/os-release
	sed -i $file \
		-e 's,NAME=.*,NAME=\"Garuda Linux\",' \
		-e 's,PRETTY_NAME=.*,PRETTY_NAME=\"Garuda Linux\",' \
		-e 's,ID=.*,ID=garuda,' \
		-e 's,ID_LIKE=.*,ID_LIKE=arch,' \
		-e 's,BUILD_ID=.*,BUILD_ID=rolling,' \
		-e 's,HOME_URL=.*,HOME_URL=\"https://garudalinux.org/\",' \
		-e 's,DOCUMENTATION_URL=.*,DOCUMENTATION_URL=\"https://wiki.garudalinux.org/\",' \
		-e 's,SUPPORT_URL=.*,SUPPORT_URL=\"https://forum.garudalinux.org/\",' \
		-e 's,BUG_REPORT_URL=.*,BUG_REPORT_URL=\"https://gitlab.com/groups/garuda-linux/\",' \
		-e 's,LOGO=.*,LOGO=garudalinux,'

	if [ -z "$(grep "^ID_LIKE=" $file)" ] && [ -n "$(grep "^ID=" $file)" ]; then
		# add missing ID_LIKE=
		sed -i $file -e '/^ID=/a \ID_LIKE=arch'
	fi

	sed -i 's|Arch|Garuda|g' /etc/issue /usr/share/factory/etc/issue
}

Lsb_release() {
	local file=/etc/lsb-release

	if [ -z "$(grep "^DISTRIB_CODENAME=" $file)" ]; then
		# add missing DISTRIB_CODENAME=
		echo "DISTRIB_CODENAME=rolling" >>$file
	fi
	sed -i $file \
		-e 's,DISTRIB_ID=.*,DISTRIB_ID=Garuda,' \
		-e 's,DISTRIB_RELEASE=.*,DISTRIB_RELEASE=Soaring,' \
		-e 's,DISTRIB_CODENAME=.*,DISTRIB_CODENAME="Broadwing",' \
		-e 's,DISTRIB_DESCRIPTION=.*,DISTRIB_DESCRIPTION=\"Garuda Linux Broadwing\",'
}

Post() {
	/usr/bin/sync
	nohup /usr/share/libalpm/scripts/garuda-hooks-runner post_back &
}

Post_background() {
	# Did this transaction install or upgrade a package? Other actions are not considered partial upgrades.
	if [[ ! -z $(tac /var/log/pacman.log | gawk '/\[ALPM\] transaction completed/ {
  begin = 1
}

/\[ALPM\] transaction started/ {
  exit
}

/ installed| upgraded/ {
  if(begin) {
    print
  }
}' | grep -vE 'garuda-update|garuda-hotfixes|.*-keyring') ]]; then
		# Is the system fully up-to-date? If not, this is a partial upgrade.
		if [ -z "$(pacman -Qu | grep -vE '\[ignored\]$')" ]; then
			rm -f /var/lib/garuda/partial_upgrade
			touch /var/lib/garuda/last_update
		else
			touch -a /var/lib/garuda/partial_upgrade
		fi
	fi
}

Snapshot() {
	if [ -x "/usr/lib/garuda/is-snapshot-boot" ] && /usr/lib/garuda/is-snapshot-boot && [[ ! -v GARUDA_SNAPSHOT_PACMAN ]]; then
		echo -e "\033[1;31mError: You are currently booted into a snapshot. Please restore the snapshot via btrfs-assistant or snapper-tools before performing pacman transactions.\n\033[1;34mNote: You can ignore this error by setting GARUDA_SNAPSHOT_PACMAN: sudo GARUDA_SNAPSHOT_PACMAN=1 pacman [...]\n\033[1;31mAny modifications made to this snapshot will be lost next reboot.\033[0m"
		exit 1
	fi
}

Grub-update() {
	# If we don't pass this, we don't need to do anything anyway
	if [ -d "/boot/efi/EFI" ] && [ -x "/usr/bin/efibootmgr" ]; then
		local current_grub_entry="$(efibootmgr | awk 'match($0,/^BootCurrent: ([0-9a-fA-F]{4})$/,out) { current=out[1] } match($0,/^Boot([0-9a-fA-F]{4})\*? ([^:]+)\t/,out) { if (out[1]==current) print out[2] }')"
		local should_act_safe=true
		local did_update=false
		local fallback_is_same=false
		local secureboot_enabled=false
		if [ -f "/etc/garuda/secureboot/enabled" ]; then
			secureboot_enabled=true
		fi

		# We can assume it's safe to update this bootloader if it exists, because this is supposed to be ours. The user will know about it at the end of the update and right here too.
		if [ -f "/boot/efi/EFI/Garuda/grubx64.efi" ]; then
			update-grub
			echo -e "\033[1;34m\n\nThe GRUB bootloader at EFI/Garuda is being updated!\n\n\033[0m"
			if [ "$secureboot_enabled" == "true" ]; then
				cmp -s "/boot/efi/EFI/Garuda/grubx64.efi" "/boot/efi/EFI/Boot/grubx64.efi" && fallback_is_same=true

				grub_modules="$(awk '/insmod ([^ ]+)$/ {print $2}' /boot/grub/grub.cfg)"
				grub_default_modules=(all_video boot btrfs cat chain configfile ext2 echo efifwsetup font gettext gfxmenu gfxterm gfxterm_background halt help keystatus loadenv loopback linux ls lsefi lsefimmap lsefisystab memdisk minicmd normal ntfs password_pbkdf2 png probe reboot regexp search search_fs_uuid search_fs_file search_label sleep smbios test true video)
				declare -A grub_installed_modules
				for mod in $grub_modules "${grub_default_modules[@]}"; do
					if [ -f "/usr/lib/grub/x86_64-efi/${mod}.mod" ]; then
						grub_installed_modules["$mod"]=1
					fi
				done
				key_path="/var/lib/garuda/secureboot/keys"
				grub-install --no-nvram --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id="Garuda" --modules "${!grub_installed_modules[*]}" --sbat /usr/share/grub/sbat.csv && \
					echo -e "\033[1;34mSigning the GRUB bootloader for secure boot...\033[0m" && \
					sbsign --key "${key_path}/MOK.key" --cert "${key_path}/MOK.crt" --output "/boot/efi/EFI/Garuda/grubx64.efi" "/boot/efi/EFI/Garuda/grubx64.efi" && \
					did_update=true
			else
				cmp -s "/boot/efi/EFI/Garuda/grubx64.efi" "/boot/efi/EFI/Boot/bootx64.efi" && fallback_is_same=true
				grub-install --no-nvram --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id="Garuda" && did_update=true
			fi
			if [ "$fallback_is_same" == "true" ] && [ "$did_update" == "true" ]; then
				if [ "$secureboot_enabled" == "true" ]; then
					cp "/boot/efi/EFI/Garuda/grubx64.efi" "/boot/efi/EFI/Boot/grubx64.efi"
				else
					cp "/boot/efi/EFI/Garuda/grubx64.efi" "/boot/efi/EFI/Boot/bootx64.efi"
				fi
			fi
		fi

		if [ "${current_grub_entry,,}" == "garuda" ] && [ "$did_update" == "true" ]; then
			should_act_safe=false
		fi

		if [ "$did_update" != "true" ]; then
			garudalib_add_update_notice "The GRUB bootloader could not be updated automatically safely."
			exit 1
		elif [ "$should_act_safe" == "true" ]; then
			garudalib_add_update_notice "The GRUB bootloader at /EFI/Garuda was updated, but it seems like you are not using the Garuda Linux bootloader by default. If you are using 'rEFInd' bootloader, you can safely ignore this. Otherwise, please change your EFI boot priorities to prioritize the \"Garuda\" bootloader. https://wiki.garudalinux.org/en/why-garuda-bootloader"
		else
			garudalib_add_update_notice "The GRUB bootloader at /EFI/Garuda has been updated/reinstalled using 'grub-install'. If this looks correct, no further action has to be taken."
		fi
	fi
}

Grub-btrfs-config() {
	local filename="/etc/default/grub-btrfs/config"
	if [ -f "${filename}" ]; then
		grep -q 'garuda_grub_btrfs_d' $filename
		if [ $? == 1 ]; then
			gawk -i inplace 'ENDFILE {
		print "\n# This config file imports drop-in files from /etc/default/grub-btrfs/config.d/.\nfor garuda_grub_btrfs_d in ${sysconfdir}/default/grub-btrfs/config.d/*.cfg ; do if [ -e \"${garuda_grub_btrfs_d}\" ]; then source \"${garuda_grub_btrfs_d}\"; fi; done"
	  }
	  1' $filename
		fi
	fi
}

Mkinitcpio-Install() {
	if [ ! -e /usr/share/libalpm/hooks/90-dracut-install.hook ]; then
		# Delegate this to the official script
		# Also run the right once since Arch Linux upstream merged install/remove into one
		if [ -x /usr/share/libalpm/scripts/mkinitcpio-install ]; then
			/usr/share/libalpm/scripts/mkinitcpio-install
			rm -f /var/lib/garuda/initramfs_error
		elif [ -x /usr/share/libalpm/scripts/mkinitcpio ]; then
			/usr/share/libalpm/scripts/mkinitcpio install
			rm -f /var/lib/garuda/initramfs_error
		else
			# We should let the user know
			echo -e "\n\033[1;34m\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\nThe kernel update failed to determine how to update initramfs.\nYou will need to update manually using mkinitcpio or dracut yourself or your system WILL NOT BE BOOTABLE.\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nWaiting 10 seconds.\n\033[0m"
			garudalib_add_update_notice "The kernel update failed to determine how to update initramfs.\nYou will need to update manually using mkinitcpio or dracut yourself or your system WILL NOT BE BOOTABLE."
			sleep 10
			touch /var/lib/garuda/initramfs_error
		fi
	fi
}

Main() {
	local hookname="$1"

	case "$hookname" in
	snapshot) Snapshot ;;
	filesystem) Filesystem ;;
	lsb-release) Lsb_release ;;
	grub-btrfs-config) Grub-btrfs-config ;;
	post) Post ;;
	post_back) Post_background ;;
	grub-update) Grub-update ;;
	kernel) Mkinitcpio-Install ;;
	"")
		Filesystem
		Lsb_release
		Grub-btrfs-config
		;;
	esac
}

Main "$@"
