#!/usr/bin/env bash

MODULE_GRUB_THEME_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULE_GRUB_THEME_PROJECT_ROOT="$(cd "$MODULE_GRUB_THEME_DIR/../../.." && pwd)"

# shellcheck source=lib/package.sh
source "$MODULE_GRUB_THEME_PROJECT_ROOT/lib/package.sh"
# shellcheck source=modules/boot/grub-theme/config.sh
source "$MODULE_GRUB_THEME_DIR/config.sh"
# shellcheck source=modules/boot/grub-theme/metadata.conf
source "$MODULE_GRUB_THEME_DIR/metadata.conf"

module_grub_theme_metadata() {
  printf '%s|%s|%s\n' "$MODULE_ID" "$MODULE_NAME" "$MODULE_DESCRIPTION"
}

module_grub_theme_settings_path() {
  printf '%s/%s\n' "$MODULE_GRUB_THEME_PROJECT_ROOT" "$POSTINSTALL_GRUB_THEME_SETTINGS_FILE"
}

module_grub_theme_settings() {
  local config_path=""
  local theme_archive=""
  local default_mode="$POSTINSTALL_GRUB_DEFAULT_MODE"
  local save_default="$POSTINSTALL_GRUB_SAVEDEFAULT"
  local timeout="$POSTINSTALL_GRUB_TIMEOUT"
  local timeout_style="$POSTINSTALL_GRUB_TIMEOUT_STYLE"
  local disable_os_prober="$POSTINSTALL_GRUB_DISABLE_OS_PROBER"
  local gfxmode="$POSTINSTALL_GRUB_GFXMODE"
  local cmdline="$POSTINSTALL_GRUB_CMDLINE_LINUX_DEFAULT"

  config_path="$(module_grub_theme_settings_path)"
  if [[ -f "$config_path" ]]; then
    while IFS='=' read -r key value; do
      case "$key" in
        theme_archive) theme_archive="$value" ;;
        default_mode) default_mode="$value" ;;
        save_default) save_default="$value" ;;
        timeout) timeout="$value" ;;
        timeout_style) timeout_style="$value" ;;
        disable_os_prober) disable_os_prober="$value" ;;
        gfxmode) gfxmode="$value" ;;
        cmdline_linux_default) cmdline="$value" ;;
      esac
    done < <(
      awk '
        /^[[:space:]]*theme_archive:/ { sub(/^[^:]+:[[:space:]]*/, "", $0); print "theme_archive=" $0 }
        /^[[:space:]]*default_mode:/ { print "default_mode=" $2 }
        /^[[:space:]]*save_default:/ { print "save_default=" $2 }
        /^[[:space:]]*timeout:/ { print "timeout=" $2 }
        /^[[:space:]]*timeout_style:/ { print "timeout_style=" $2 }
        /^[[:space:]]*disable_os_prober:/ { print "disable_os_prober=" $2 }
        /^[[:space:]]*gfxmode:/ { print "gfxmode=" $2 }
        /^[[:space:]]*cmdline_linux_default:/ {
          sub(/^[^:]+:[[:space:]]*/, "", $0)
          print "cmdline_linux_default=" $0
        }
      ' "$config_path"
    )
  fi

  printf '%s|%s|%s|%s|%s|%s|%s|%s\n' \
    "$theme_archive" \
    "$default_mode" \
    "$save_default" \
    "$timeout" \
    "$timeout_style" \
    "$disable_os_prober" \
    "$gfxmode" \
    "$cmdline"
}

module_grub_theme_current_cmdline() {
  local grub_file="/etc/default/grub"

  if [[ ! -f "$grub_file" ]]; then
    printf '\n'
    return 0
  fi

  awk -F'"' '/^GRUB_CMDLINE_LINUX_DEFAULT=/{ print $2; exit }' "$grub_file"
}

module_grub_theme_extra_cmdline_options() {
  local desired_cmdline="$1"
  local current_cmdline=""
  local option=""
  local extras=""

  current_cmdline="$(module_grub_theme_current_cmdline)"

  for option in $current_cmdline; do
    if [[ " $desired_cmdline " != *" $option "* ]]; then
      extras="${extras:+$extras }$option"
    fi
  done

  printf '%s\n' "$extras"
}

module_grub_theme_merge_cmdline_options() {
  local desired_cmdline="$1"
  local extra_cmdline="$2"
  local merged="$desired_cmdline"
  local option=""

  for option in $extra_cmdline; do
    if [[ " $merged " != *" $option "* ]]; then
      merged="${merged:+$merged }$option"
    fi
  done

  printf '%s\n' "$merged"
}

module_grub_theme_archive_dir() {
  local candidates=(
    "$MODULE_GRUB_THEME_PROJECT_ROOT/$POSTINSTALL_GRUB_THEME_ARCHIVE_DIR_PRIMARY"
    "$MODULE_GRUB_THEME_PROJECT_ROOT/$POSTINSTALL_GRUB_THEME_ARCHIVE_DIR_SECONDARY"
    "$MODULE_GRUB_THEME_PROJECT_ROOT/$POSTINSTALL_GRUB_THEME_ARCHIVE_DIR_FALLBACK"
  )
  local candidate=""

  for candidate in "${candidates[@]}"; do
    if [[ -d "$candidate" ]] && find "$candidate" -maxdepth 1 -type f \( -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) | grep -q .; then
      printf '%s\n' "$candidate"
      return 0
    fi
  done

  printf '%s\n' "$MODULE_GRUB_THEME_PROJECT_ROOT/$POSTINSTALL_GRUB_THEME_ARCHIVE_DIR_FALLBACK"
}

module_grub_theme_list_archives() {
  local archive_dir=""
  archive_dir="$(module_grub_theme_archive_dir)"
  find "$archive_dir" -maxdepth 1 -type f \( -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) -printf '%f\n' | sort
}

module_grub_theme_archive_label() {
  local archive_name="$1"
  local label=""

  label="${archive_name%.zip}"
  label="${label%.tar.gz}"
  label="${label%.tgz}"
  label="${label//-/ }"
  printf '%s\n' "$label"
}

module_grub_theme_extract() {
  local archive_name="$1"
  local archive_dir=""
  local archive_path=""
  local target_dir=""
  local theme_file=""

  archive_dir="$(module_grub_theme_archive_dir)"
  archive_path="$archive_dir/$archive_name"
  target_dir="$POSTINSTALL_GRUB_THEME_INSTALL_DIR/${archive_name%.*}"

  if [[ ! -f "$archive_path" ]]; then
    ui_error "Archive GRUB introuvable : $archive_path"
    return 1
  fi

  mkdir -p "$target_dir"

  case "$archive_name" in
    *.zip)
      if ! package_is_installed unzip; then
        package_refresh_indexes
        package_install unzip
      fi
      unzip -o "$archive_path" -d "$target_dir" >/dev/null
      ;;
    *.tar.gz|*.tgz)
      tar -xzf "$archive_path" -C "$target_dir"
      ;;
    *)
      ui_error "Archive de theme non supportee : $archive_name"
      return 1
      ;;
  esac

  theme_file="$(find "$target_dir" -type f -name 'theme.txt' | head -n 1)"
  if [[ -z "$theme_file" ]]; then
    ui_error "Aucun fichier theme.txt detecte dans l'archive $archive_name"
    return 1
  fi

  printf '%s\n' "$theme_file"
}

module_grub_theme_backup_config() {
  if [[ -f "$POSTINSTALL_GRUB_THEME_CONFIG_FILE" ]]; then
    cp "$POSTINSTALL_GRUB_THEME_CONFIG_FILE" "$POSTINSTALL_GRUB_THEME_CONFIG_BACKUP_FILE"
  fi
}

module_grub_theme_preview() {
  local archive_name="$1"
  local default_mode="$2"
  local timeout="$3"
  local timeout_style="$4"
  local disable_os_prober="$5"
  local archive_dir=""

  archive_dir="$(module_grub_theme_archive_dir)"
  ui_info "Archive selectionnee : $archive_name"
  ui_info "Source : $archive_dir/$archive_name"
  ui_info "Demarrage par defaut : $default_mode"
  ui_info "Timeout menu : $timeout"
  ui_info "Style menu : $timeout_style"
  ui_info "Detection autres OS : $disable_os_prober"
}

module_grub_theme_install() {
  local archive_name="${1:-}"
  local default_mode="${2:-}"
  local save_default="${3:-}"
  local timeout="${4:-}"
  local timeout_style="${5:-}"
  local disable_os_prober="${6:-}"
  local gfxmode="${7:-}"
  local cmdline="${8:-}"
  local settings=""
  local theme_path=""

  settings="$(module_grub_theme_settings)"
  IFS='|' read -r \
    default_archive \
    settings_default_mode \
    settings_save_default \
    settings_timeout \
    settings_timeout_style \
    settings_disable_os_prober \
    settings_gfxmode \
    settings_cmdline <<< "$settings"

  archive_name="${archive_name:-$default_archive}"
  default_mode="${default_mode:-$settings_default_mode}"
  save_default="${save_default:-$settings_save_default}"
  timeout="${timeout:-$settings_timeout}"
  timeout_style="${timeout_style:-$settings_timeout_style}"
  disable_os_prober="${disable_os_prober:-$settings_disable_os_prober}"
  gfxmode="${gfxmode:-$settings_gfxmode}"
  cmdline="${cmdline:-$settings_cmdline}"

  if [[ -z "$archive_name" ]]; then
    ui_error "Aucune archive de theme specifiee"
    return 1
  fi

  module_grub_theme_preview "$archive_name" "$default_mode" "$timeout" "$timeout_style" "$disable_os_prober"
  mkdir -p /etc/default/grub.d
  module_grub_theme_backup_config
  theme_path="$(module_grub_theme_extract "$archive_name")" || return 1

  cat > "$POSTINSTALL_GRUB_THEME_CONFIG_FILE" <<EOF
GRUB_THEME="$theme_path"
GRUB_DEFAULT=$default_mode
GRUB_SAVEDEFAULT=$save_default
GRUB_TIMEOUT=$timeout
GRUB_TIMEOUT_STYLE=$timeout_style
GRUB_DISABLE_OS_PROBER=$disable_os_prober
GRUB_GFXMODE=$gfxmode
GRUB_CMDLINE_LINUX_DEFAULT="$cmdline"
EOF
  update-grub

  log_info "Theme GRUB configure : $archive_name"
  ui_success "Theme GRUB configure : $archive_name"
}

module_grub_theme_test() {
  test -f "$POSTINSTALL_GRUB_THEME_CONFIG_FILE" || return 1
  grep -q '^GRUB_THEME=' "$POSTINSTALL_GRUB_THEME_CONFIG_FILE" || return 1
  grep -q '^GRUB_DEFAULT=' "$POSTINSTALL_GRUB_THEME_CONFIG_FILE" || return 1
  grep -q '^GRUB_TIMEOUT=' "$POSTINSTALL_GRUB_THEME_CONFIG_FILE" || return 1
  test -d "$(module_grub_theme_archive_dir)" || return 1
  test -f "$(module_grub_theme_settings_path)" || return 1
}
