LIMINE_LOCK_FILE="/tmp/limine-global.lock"

mutex_lock() {
	local name=$1
	exec 200>${LIMINE_LOCK_FILE} || {
		rm -f ${LIMINE_LOCK_FILE}
		exec 200>${LIMINE_LOCK_FILE}
	}
	flock --timeout=10 200 || {
		echo -e "\033[1;31m Mutex lock timeout on ${name}.\033[0m" >&2
		return 1
	}
}

mutex_unlock() {
	# Release the lock
	flock --unlock 200
}

### Check if the system is using UEFI
check_uefi() {
	if [[ ! -d /sys/firmware/efi ]]; then
		return 1
	fi
	return 0
}

is_x64() {
	[[ "$(uname -m)" == "x86_64" ]]
}

### Load key=value config
load_key_value_config() {
	local file="$1"
	while IFS= read -r line || [[ -n "$line" ]]; do
		# Skip blank lines and comments
		[[ "$line" =~ ^[[:space:]]*(#.*)?$ ]] && continue

		# Match VAR = value
		if [[ "$line" =~ ^[[:space:]]*([A-Za-z_][A-Za-z0-9_]*)[[:space:]]*=[[:space:]]*(.*)$ ]]; then
			local var="${BASH_REMATCH[1]}"
			local val="${BASH_REMATCH[2]}"
			val="${val%\"}"
			val="${val#\"}"
			export "$var"="$val"
		fi
	done <"$file"
}

### Load configuration
load_config() {
	local usr_d_dir="/usr/share/limine-entry-tool.d"
	local etc_conf="/etc/limine-entry-tool.conf"
	local etc_d_dir="/etc/limine-entry-tool.d"
	# /etc/default/limine is the central config read by all Limine-based packages
	local default_conf="/etc/default/limine"

	# 1. Load all /usr/share/limine-entry-tool.d/*.conf (lowest priority)
	if [[ -d "$usr_d_dir" ]]; then
		for file in "$usr_d_dir"/*.conf; do
			[[ -f "$file" ]] || continue
			load_key_value_config "$file"
		done
	fi

	# 2. Load /etc/limine-entry-tool.conf
	if [[ -f "$etc_conf" ]]; then
		load_key_value_config "$etc_conf"
	fi

	# 3. Load all /etc/limine-entry-tool.d/*.conf
	if [[ -d "$etc_d_dir" ]]; then
		for file in "$etc_d_dir"/*.conf; do
			[[ -f "$file" ]] || continue
			load_key_value_config "$file"
		done
	fi

	# Do not use ENABLE_ENROLL_LIMINE_CONFIG in any random configs
	ENABLE_ENROLL_LIMINE_CONFIG=""

	# 4. Load /etc/default/limine (highest priority)
	if [[ -f "$default_conf" ]]; then
		load_key_value_config "$default_conf"
	fi

	# Detect ESP_PATH if not set
	if [[ -z "${ESP_PATH:-}" || -z "${ESP_PATH// /}" ]]; then
		if check_uefi && command -v bootctl &>/dev/null; then
			ESP_PATH=$(bootctl --print-esp-path 2>/dev/null)
			if [[ -z "${ESP_PATH}" ]]; then
				echo -e "\033[1;31m Error: Cannot detect an ESP path. Please set ESP_PATH in '$default_conf'.\033[0m" >&2
				return 1
			fi
		else
			echo -e "\033[1;31m Error: Please set ESP_PATH in '$default_conf'.\033[0m" >&2
			return 1
		fi
	fi
	return 0
}

### Check if a given path is a valid EFI System Partition (ESP)
check_esp() {
	local path="$1"

	### Check if the path exists and is a directory
	if [[ ! -d "$path" ]]; then
		echo -e "\033[1;31m Error: The specified ESP path '$path' does not exist or is not a directory.\033[0m" >&2
		return 1
	fi

	### Check if the path is mounted
	if ! mountpoint -q "$path"; then
		echo -e "\033[1;31m Error: FAT32 boot partition is not mounted at '$path'.\033[0m" >&2
		return 1
	fi

	### Check if the filesystem type is FAT (EFI System Partitions use FAT)
	local fsType
	read -r fsType < <(findmnt -n -o FSTYPE "$path")
	if [[ "$fsType" != "vfat" ]]; then
		echo -e "\033[1;31m Error: The mounted ESP '$path' is not of type 'FAT32'.\033[0m" >&2
		return 1
	fi

	#echo "Success: The path '$path' is a valid ESP."
	return 0
}

### Get machine-id
get_machine_id() {
	local machine_id_path="/etc/machine-id"

	# Generate if missing or empty
	if [[ ! -s "$machine_id_path" ]]; then
		echo "Generating machine-id at $machine_id_path..."
		uuidgen | tr -d '-' | head -c 32 >"$machine_id_path" || return 1
		# Set ownership and permissions
		chmod 444 "$machine_id_path"
		chown root:root "$machine_id_path"
	fi

	# Read and export
	# shellcheck disable=SC2034
	MACHINE_ID=$(<"$machine_id_path")
	return 0
}

### Get a version of Limine binary
get_limine_version() {
	local file=$1

	# Helper function:
	# Runs the given command with the file as argument,
	# checks if output contains "limine",
	# and extracts the version number if present.
	try_cmd() {
		local output version
		if output=$("$@" 2>/dev/null); then
			# Check if output contains 'limine'
			echo "$output" | grep -qi 'limine' || return 1

			# Extract version number like 9.5 or 9.5.0
			version=$(echo "$output" | grep -E '^[0-9]+\.[0-9]+(\.[0-9]+)?$' | head -n1 | tr -d '\r[:space:]')
			[[ -n $version ]] && {
				echo "$version"
				return 0
			}
		fi
		return 1
	}

	# Try with strings if available
	if command -v strings >/dev/null 2>&1 && try_cmd strings "$file"; then
		return 0
	fi

	# Final fallback: grep -a to simulate strings
	if try_cmd grep -a -o '[[:print:]]\{4,\}' "$file"; then
		return 0
	fi

	return 1
}

get_limine_version_as_int() {
	local file=$1
	local version major minor patch

	version=$(get_limine_version "$file") || return 1

	# Split into major, minor, patch
	major=$(cut -d. -f1 <<<"$version")
	minor=$(cut -d. -f2 <<<"$version")
	patch=$(cut -d. -f3 <<<"$version")

	# Default fallback if parts are missing
	major=${major:-0}
	minor=${minor:-0}
	patch=${patch:-0}

	printf "%03d%03d%03d\n" "$major" "$minor" "$patch"
}

### Compare two files based on their embedded Limine version
### Output:
###   0 → source == target
###   1 → source > target
###   2 → source < target
###   3 → source invalid
compare_limine_versions() {
	local src="$1"
	local tgt="$2"

	local src_ver tgt_ver

	src_ver=$(get_limine_version_as_int "$src") || return 3
	tgt_ver=$(get_limine_version_as_int "$tgt") || tgt_ver=0

	# Strip leading zeros
	src_ver=$((10#$src_ver))
	tgt_ver=$((10#$tgt_ver))

	if ((src_ver == tgt_ver)); then
		return 0
	elif ((src_ver > tgt_ver)); then
		return 1
	else
		return 2
	fi
}

### Check if snapper is installed and btrfs is used
is_snapper_installed() {
	local fsType

	# Check if snapper is available
	if ! command -v snapper &>/dev/null; then
		#echo "snapper is not installed or not in PATH."
		export IS_SNAPPER_INSTALLED="no"
		return 1
	fi

	# Determine the filesystem type of the root mount
	read -r fsType < <(findmnt -n -o FSTYPE "/")
	if [[ "$fsType" == "btrfs" || "$fsType" == "overlay" ]]; then
		export IS_SNAPPER_INSTALLED="yes"
		return 0
	fi

	export IS_SNAPPER_INSTALLED="no"
	return 1
}

### Check if secure boot is installed
is_sb_installed() {
	# Check if sbctl is available
	if ! command -v sbctl &>/dev/null; then
		#echo "sbctl is not installed or not in PATH."
		export IS_SB_INSTALLED="no"
		return 1
	fi

	local sb_status
	sb_status=$(sbctl status)
	if echo "$sb_status" | grep -q "not installed"; then
		export IS_SB_INSTALLED="no"
		return 1
	fi

	if echo "$sb_status" | grep -q "Secure Boot:.*Disabled"; then
		echo "Secure Boot is disabled. Signing may not be effective."
	fi
	export IS_SB_INSTALLED="yes"
}

### Secure boot sign
sb_sign() {
	is_x64 || return 0
	check_uefi || return 0
	local file_path=$1
	if [[ "$IS_SB_INSTALLED" != "yes" ]]; then
		return 0
	fi
	# Check if the file exists
	if [[ ! -f "$file_path" ]]; then
		echo -e "\033[1;31mError: File '$file_path' does not exist.\033[0m" >&2
		return 1
	fi

	# Sign the file using sbctl
	if ! sbctl sign "$file_path"; then
		echo -e "\033[1;31mError: Failed to sign the file '$file_path'.\033[0m" >&2
		return 1
	fi
	return 0
}

### Sync cached writes to FAT32 to prevent data loss in case of power failure or forced shutdown.
sync_file() {
	if [[ -f "${BINARY_TARGET_PATH}" ]]; then
		# Do not use the -d option, as it applies to Linux file systems but not to FAT32. Use -f instead.
		sync -f "${BINARY_TARGET_PATH}"
	fi
}

restore_limine_binary() {
	# Restore the binary file from backup
	if [[ -f "$BINARY_BACKUP_PATH" ]]; then
		local backup_hash
		local target_hash
		backup_hash=$(tar --to-command="b2sum" -xf "$BINARY_BACKUP_PATH" | awk '{print $1}')
		if [[ -f "$BINARY_TARGET_PATH" ]]; then
			target_hash=$(b2sum "$BINARY_TARGET_PATH" | awk '{print $1}')
		else
			target_hash=""
		fi
		if [[ "$backup_hash" != "$target_hash" ]]; then
			if ! tar -xf "$BINARY_BACKUP_PATH" --directory="${LIMINE_DIR_PATH}" "${LIMINE_EFI_FILE}"; then
				echo -e "\033[1;31mError: Failed to restore '$BINARY_BACKUP_PATH' to '$BINARY_TARGET_PATH'.\033[0m" >&2
			fi
		fi
	else
		#echo -e "\033[1;31mNo backup of the Limine binary.\033[0m" >&2
		return 1
	fi
}

reset_enroll_config() {
	is_x64 || return 0
	check_uefi || return 0
	if restore_limine_binary; then
		return 0
	fi
	if [[ -f "$BINARY_TARGET_PATH" ]]; then
		if ! limine enroll-config --reset "$BINARY_TARGET_PATH" --quiet; then
			echo -e "\033[1;31mError: Failed to reset the enrolled config for '$BINARY_TARGET_PATH'.\033[0m" >&2
			return 1
		fi
	fi
}

### Enroll Limine config into Limine binary file, then sign the binary.
enroll_config() {
	is_x64 || return 0
	check_uefi || return 0
	restore_limine_binary
	if [[ -f "$LIMINE_CONFIG_PATH" && "$ENABLE_ENROLL_LIMINE_CONFIG" == "yes" ]]; then
		# Attempt to enroll the config file
		if ! limine enroll-config "$BINARY_TARGET_PATH" "$(b2sum "$LIMINE_CONFIG_PATH" | awk '{print $1}')"; then
			echo -e "\033[1;31mError: Failed to enroll the config '$LIMINE_CONFIG_PATH' into '$BINARY_TARGET_PATH'.\033[0m" >&2
			restore_limine_binary
		fi
	fi
	sb_sign "${BINARY_TARGET_PATH}"
	sync_file
}

are_snapper_and_sb_installed() {
	if [[ "$IS_SB_INSTALLED" == "yes" && "$IS_SNAPPER_INSTALLED" == "yes" ]]; then
		return 0
	else
		return 1
	fi
}

### Main Header Logic
initialize_header() {
	load_config || return 1
	check_esp "$ESP_PATH" || return 1
	get_machine_id || return 1
	is_sb_installed
	is_snapper_installed

	# Source and target file paths
	if [[ -n "${LIMINE_BINARY_PATH:-}" ]]; then
		export BINARY_SOURCE_PATH="$LIMINE_BINARY_PATH"
	else
		export BINARY_SOURCE_PATH="/usr/share/limine/BOOTX64.EFI"
	fi

	export LIMINE_DIR_PATH="${ESP_PATH}/EFI/limine/"
	export LIMINE_EFI_FILE="limine_x64.efi"
	export LIMINE_BACKUP_FILE="limine_x64.bak"

	export BINARY_TARGET_PATH="${LIMINE_DIR_PATH}${LIMINE_EFI_FILE}"
	export BINARY_BACKUP_PATH="${LIMINE_DIR_PATH}${LIMINE_BACKUP_FILE}"
	export BINARY_FALLBACK_PATH="${ESP_PATH}/EFI/BOOT/BOOTX64.EFI"

	export LIMINE_EFI_PATH="\\EFI\\limine\\${LIMINE_EFI_FILE}"
	export LIMINE_CONFIG_PATH="${ESP_PATH}/limine.conf"
	return 0
}
