#!/bin/bash
# elilongsetup - UEFI Installer for Slackware
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2026 Tim Dickson
VERSION="@@VERSION@@"
SUBDIR="@@SUBDIR@@"
DISTRO="@@DISTRO@@"
DEFAULT_MNT="@@DEF_MNT@@"
STAGEDIR="@@STAGEDIR@@"
T_MNT=""
WAS_MOUNTED=0
WIN_BOOT="\\EFI\\Microsoft\\Boot\\bootmgfw.efi"
WIN_FOUND=0

trap '{ echo -e "\nInstallation aborted by user."; exit 0; }' SIGINT
echo "elilongsetup v$VERSION"
echo "Target: EFI/$SUBDIR/ (Staging from $STAGEDIR)"
echo "------------------------------------------------------"
if [[ "$EUID" -ne 0 ]]; then
  echo "Error: Please run as root.";
  exit 1;
fi
# 1. Find the ESP
ESP_COUNT=0
declare -a RAW_LIST
echo "Scanning block devices for EFI System Partitions..."

while read -r line; do
  eval "$line"
  if [[ "$TYPE" == "disk" ]]; then
    DRV_MODEL="$MODEL"
    DRV_NAME="$NAME"
  fi

  # GUID for EFI System Partition
  if [[ "$TYPE" == "part" && "$PARTTYPE" == "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" ]]; then
    ((ESP_COUNT++))
    RAW_LIST+=("$ESP_COUNT|$NAME|$SIZE|$DRV_NAME ($DRV_MODEL)|$MOUNTPOINT")
  fi
done < <(lsblk -P -o NAME,SIZE,MODEL,MOUNTPOINT,PARTTYPE,TYPE)

if [[ $ESP_COUNT -eq 0 ]]; then
  echo "Error: No EFI System Partitions found."
  exit 1
elif [[ $ESP_COUNT -eq 1 ]]; then
  IFS='|' read -r idx T_DEV T_SIZE T_DRV T_MNT <<< "${RAW_LIST[0]}"
  echo "Found EFI Partition: $T_DEV ($T_SIZE) on $T_DRV"
  read -p "Proceed with installation? [Y/q]: " conf
  [[ "$conf" =~ ^[Qq]$ ]] && { echo "Aborted."; exit 0; }
else
  echo "Multiple ESPs detected. Select target or 'q' to quit:"
  for item in "${RAW_LIST[@]}"; do
    IFS='|' read -r idx dev size drv mnt <<< "$item"
    printf "%d) %-15s %-8s %-25s (Mount: %s)\n" "$idx" "$dev" "$size" "$drv" "${mnt:-None}"
  done
  echo " q) Quit"
  while true; do
    read -p "Selection [1-$ESP_COUNT or q]: " choice
    if [[ "$choice" =~ ^[Qq]$ ]]; then
      echo "Installation cancelled."
      exit 0
    fi
    if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ESP_COUNT )); then
      IFS='|' read -r idx T_DEV T_SIZE T_DRV T_MNT <<< "${RAW_LIST[$((choice-1))]}"
      break
    else
      echo "Invalid entry. Enter 1-$ESP_COUNT or 'q' to exit."
    fi
  done
fi

#DEFAULT_ESP="/boot/efi"
if [[ -n "$T_MNT" ]]; then
  FINAL_ESP_PATH="$T_MNT"
  WAS_MOUNTED=1
  echo "Using existing mount point: $FINAL_ESP_PATH"
else
  if mountpoint -q "$DEFAULT_MNT"; then
    echo "Warning: $DEFAULT_MNT is already in use by another device."
    while true; do
      read -p "Enter a different temporary mount point: [/mnt/tmp_esp]" alt_mnt
      if [[ "$alt_mnt" == "$DEFAULT_MNT" ]]; then
        echo "Error: That path is currently busy. Please choose another."
      elif [[ -z "$alt_mnt" ]]; then
        alt_mnt=/mnt/tmp_esp
        FINAL_ESP_PATH="$alt_mnt"
        break
      else
        FINAL_ESP_PATH="$alt_mnt"
        break
      fi
    done
  else
    FINAL_ESP_PATH="$DEFAULT_MNT"
  fi
  echo "Preparing to mount /dev/$T_DEV to $FINAL_ESP_PATH..."
  if [[ ! -d "$FINAL_ESP_PATH" ]]; then
    mkdir -p "$FINAL_ESP_PATH" || { echo "Error: Failed to create $FINAL_ESP_PATH"; exit 1; }
  fi
  mount "/dev/$T_DEV" "$FINAL_ESP_PATH" || { echo "Error: Mount failed!"; exit 1; }
fi
#check for windows uefi installation
if [ -f "${MNT}/EFI/Microsoft/Boot/bootmgfw.efi" ]; then
  WIN_FOUND=1
fi
#small function used for injecting message file for distro this was compiled on.
print_welcome_message() {
cat << 'EOF'
@@DISTMESS@@
EOF
}
INSTALL_PATH="$FINAL_ESP_PATH/EFI/$SUBDIR"
SOURCE_BIN="$STAGEDIR/elilong.efi"
if [[ -f "$SOURCE_BIN" ]]; then
  mkdir -p "$INSTALL_PATH" 2>/dev/null
  if [[ -d "$INSTALL_PATH" && -w "$INSTALL_PATH" ]]; then
    DO_COPY=1
    if [[ -f "$INSTALL_PATH/elilong.efi" ]]; then
      SUM1=$(md5sum "$SOURCE_BIN" | cut -d' ' -f1)
      SUM2=$(md5sum "$INSTALL_PATH/elilong.efi" | cut -d' ' -f1)
      [[ "$SUM1" == "$SUM2" ]] && DO_COPY=0
    fi
    if [[ $DO_COPY -eq 1 ]]; then
      cp -v "$SOURCE_BIN" "$INSTALL_PATH/elilong.efi"
    else
      echo "elilong.efi is already up to date. Skipping copy."
    fi
    echo "Synchronizing boot assets from /boot..."
    # Define assets to sync (Target Name | Source Pattern)
    # We resolve symlinks using readlink -f
    ASSETS=("vmlinuz|/boot/vmlinuz" "initrd.gz|/boot/initrd.gz" "System.map|/boot/System.map")
    for asset in "${ASSETS[@]}"; do
      IFS='|' read -r target source_path <<< "$asset"
      if [[ -e "$source_path" ]]; then
        #make sure we copy actual file, as the fat32 based ESP cannot handle links.
        REAL_SOURCE=$(readlink -f "$source_path")
        echo "Copying $target (from $REAL_SOURCE)..."
        cp -L "$REAL_SOURCE" "$INSTALL_PATH/$target"
      fi
    done
    ELCONF="$INSTALL_PATH/elilong.conf"
    if [[ ! -f "$ELCONF" ]]; then
      PARTUUID="$(lsblk -dno PARTUUID "/dev/$T_DEV")"
      echo "Generating initial configuration $ELCONF..."
      echo "# elilong.conf generated by elilongsetup v$VERSION created "$(date +"%Y-%m-%d")"." > "$ELCONF"
      echo "# Note: All paths should be relative to the efi partition mount. elilo can only read" >> "$ELCONF"
      echo "# the uefi system partition which is fat formatted so links are not valid" >> "$ELCONF"
      echo "# delay: tenths of a second to wait (50 is 5s, max value 1200 is 2mins )" >> "$ELCONF"
      echo "# before booting default entry, or first one if default is not defined." >> "$ELCONF"
      echo "# Set to 'wait' to wait indefiniely, or 0 to boot without waiting." >> "$ELCONF"
      echo "# message=\\EFI\\$SUBDIR\\message.txt" >> "$ELCONF"
      echo "prompt" >> "$ELCONF"
      echo "delay=50" >> "$ELCONF"
      echo "default=$DISTRO" >> "$ELCONF"
      echo "" >> "$ELCONF"
      echo "# elilong configuration for $DISTRO" >> "$ELCONF"
      echo "image=\\EFI\\$SUBDIR\\vmlinuz" >> "$ELCONF"
      echo "  label=$DISTRO" >> "$ELCONF"
      echo "  description=$DISTRO vmlinuz" >>"$ELCONF"
      if [[ -e "/boot/initrd.gz" ]]; then
        echo "  initrd=\\EFI\\$SUBDIR\\initrd.gz" >> "$ELCONF"
      fi
      echo "  root=PARTUUID=$PARTUUID" >> "$ELCONF"
      echo "  read-only" >> "$ELCONF"
      echo "  append=\"vga=normal\"" >> "$ELCONF"
      if [ "$WIN_FOUND" -eq 1 ]; then
        echo "" >> "$ELCONF"
        echo "# detected windows installation" >> "$ELCONF"
        echo "image=${WIN_BOOT}" >> "$ELCONF"
        echo "  label=Windows" >> "$ELCONF"
        echo "  description=MS Windows boot loader" >> "$ELCONF"
      fi
    else
      echo "Note: $ELCONF already Exists. Skipping generation."
    fi
    #lets also generate a sample message.txt file if one doesn't exist.
    ELMESS="$INSTALL_PATH/message.txt"
    if [[ ! -f "$ELMESS" ]]; then
      print_welcome_message >"$ELMESS"
    fi
    #now to add an entry in the uefi bios, removing old elilong entries.
    BOOT_LABEL="$DISTRO (elilong)"
    echo "Updating UEFI Boot Entry: $BOOT_LABEL"
    # Find and remove existing entries with the same label to prevent duplicates
    EXISTING_ENTRIES=$(efibootmgr | grep "$BOOT_LABEL" | awk '{print $1}' | sed 's/Boot//;s/\*//')
    for entry in $EXISTING_ENTRIES; do
      efibootmgr -b "$entry" -B >/dev/null
    done
    # Get the disk device (e.g., /dev/sda) and partition number (e.g., 1)
    ESP_DEV="/dev/$T_DEV"
    PART_NUM=$(echo "$T_DEV" | grep -o '[0-9]\+$')
    #remove partition number and any trailing p (for nvme)
    if echo "$T_DEV" | grep -q "nvme"; then
      DISK_DEV="/dev/$(echo "$T_DEV" | sed 's/p[0-9]\+$//')"
    else
      DISK_DEV="/dev/$(echo "$T_DEV" | sed 's/[0-9]\+$//')"
    fi
    echo "Target Partition: $ESP_DEV (Number: $PART_NUM)"
    echo "Target Disk: $DISK_DEV"
    # Create the new entry
    # Note: UEFI paths use backslashes
    efibootmgr -c -d "$DISK_DEV" -p "$PART_NUM" -L "$BOOT_LABEL" -l "\\EFI\\$SUBDIR\\elilong.efi" >/dev/null
    if [[ $? -eq 0 ]]; then
      echo "UEFI boot entry '$BOOT_LABEL' created successfully."
      echo "Success: elilong.efi deployed."
    else
      echo "Warning: Failed to create UEFI boot entry. You may need to do this manually."
    fi
  else
    echo "Error: Installation path $INSTALL_PATH does not exist or is not writable."
    # If we mounted this, we should still try to clean up before exiting
    [[ $WAS_MOUNTED -eq 0 ]] && umount "$FINAL_ESP_PATH"
    exit 1
  fi
else
  echo "Error: Source binary missing from $STAGEDIR."
  [[ $WAS_MOUNTED -eq 0 ]] && umount "$FINAL_ESP_PATH"
  exit 1
fi
if [[ $WAS_MOUNTED -eq 0 ]]; then
  echo "Unmounting temporary mount point $FINAL_ESP_PATH..."
  # Give the system a second to sync buffers
  sync
  umount "$FINAL_ESP_PATH" || echo "Warning: Failed to unmount $FINAL_ESP_PATH"
  if [[ -d "$FINAL_ESP_PATH" ]]; then
    if [[ -z "$(ls -A "$FINAL_ESP_PATH")" ]]; then
      echo "Removing empty temporary directory $FINAL_ESP_PATH..."
      rmdir "$FINAL_ESP_PATH" 2>/dev/null
    else
      echo "Notice: $FINAL_ESP_PATH is not empty; leaving directory intact."
    fi
  fi
else
  echo "Partition remains mounted at $FINAL_ESP_PATH for your use."
fi
echo "------------------------------------------------------"
echo "Setup complete."

