#!/usr/bin/env bash
# fiw-limine-splice <esp-mountpoint>
# Replaces the fiw-gentoo block in <esp>/limine.conf with the snippet Gentoo left
# at <esp>/<gentoo-machine-id>/limine-entries.conf after a Gentoo kernel update.
# Menu order (Fiw): Gentoo, CachyOS, other entries, Windows last.
set -euo pipefail
esp=${1:?usage: fiw-limine-splice <esp>}
conf=$esp/limine.conf
begin='# >>> fiw-gentoo (managed by fiw-limine, do not edit)'
end='# <<< fiw-gentoo'

shopt -s nullglob
snippets=("$esp"/*/fiw-gentoo.marker)
((${#snippets[@]} == 1)) || { echo "fiw-limine-splice: expected 1 Gentoo snippet, found ${#snippets[@]}" >&2; exit 1; }
snippet=$(dirname "${snippets[0]}")/limine-entries.conf
[[ -f $conf && -f $snippet ]] || exit 0

tmp=$conf.fiw-tmp
# Drop the old Gentoo block, split the rest into header + top-level entries
# (a top-level entry starts at a line "/X" and runs to the next one), then
# print: header, Gentoo block, CachyOS, other entries, Windows entries.
awk -v b="$begin" -v e="$end" -v snip="$snippet" '
	BEGIN {n = 0}
	$0==b {skip=1} skip {if ($0==e) skip=0; next}
	/^comment: machine-id=/ {mid=$0; next}
	/^\/[^\/]/ {n++; if (mid != "") ent[n] = mid "\n"; mid=""}
	{ ent[n] = ent[n] $0 "\n" }
	END {
		if (mid != "") ent[n] = ent[n] mid "\n"
		for (i = 1; i <= n; i++) {
			h = ent[i]; sub(/\n.*/, "", h)
			if (h ~ /^\/\+?CachyOS/) cls[i] = 1
			else if (ent[i] ~ /Windows|bootmgfw\.efi/) cls[i] = 3
			else cls[i] = 2
		}
		out = ent[0]
		sub(/\n+$/, "\n", out)
		out = out "\n" b "\n"
		while ((getline l < snip) > 0) out = out l "\n"
		out = out e "\n\n"
		for (c = 1; c <= 3; c++) for (i = 1; i <= n; i++) if (cls[i] == c) out = out ent[i]
		sub(/\n+$/, "\n", out)
		printf "%s", out
	}' "$conf" >"$tmp"

# Refuse to write if any non-Gentoo line got lost.
if ! diff <(awk -v b="$begin" -v e="$end" '$0==b{s=1} !s&&NF{print} $0==e{s=0}' "$conf" | sort) \
	<(awk -v b="$begin" -v e="$end" '$0==b{s=1} !s&&NF{print} $0==e{s=0}' "$tmp" | sort) >/dev/null; then
	rm -f "$tmp"; echo "fiw-limine-splice: reorder would change entries, leaving limine.conf alone" >&2; exit 1
fi
cmp -s "$tmp" "$conf" && { rm -f "$tmp"; exit 0; }
cp -p "$conf" "$conf.before-fiw"
mv "$tmp" "$conf"
sync -f "$conf"
