#!/usr/bin/env bash
# vim:et:ts=2:sts=2:sw=2

# Get absolute repository root (especially when symlinked)
ROOT="$(realpath "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")")"

# Load accompanying bash library
source "$ROOT/lib/lib.bash"

BTRFS="${1:-"/var/btrfs"}" # Path to system BTRFS root

if [ -n "$HELP" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
  say "
  USAGE:
    $(g "${BASH_SOURCE##*/}")  [$(c btrfs-path)]

  DESCRIPTION:
    $(g "${BASH_SOURCE##*/}") reconfigures a TechLit system
    hosted in BTRFS volume at $(c btrfs-path) (default: $(c /var/btrfs))
  "
  exit 1
fi

# Exit now unless run as admin
assert-is-admin

if [[ "$TERM" != fbterm ]]; then
  say "$(r "This script should not be run on tty1. Please switch to tty2")"
  exit 1
fi

#
# JSON helpers
#
# Create temporary json config
CONFIG="$(mktemp)"
cat "$BTRFS/@srv/secure/config.json" >"$CONFIG"

# USAGE: get role # => client
# USAGE: get gpu_hacks # => defaults,xf86-video-intel
get() { jq -r ".$1" "$CONFIG"; }

# USAGE: set role server
# USAGE: set hostname tl-0000
set() {
  UNSAVED='(unsaved changes)'
  cat <<<"$(jq ".$1 = \"$2\"" "$CONFIG")" >"$CONFIG"
}

#
# Dialog helpers
#
VERSION="$(cat "$BTRFS/@root/etc/tl-desktop-version")"
MENU_TITLE="Reconfigure TechLit System on $BTRFS (v$VERSION)"
ANSWER=
UNSAVED=

# Wrapper for dialog with shared options. Sets an $ANSWER variable before returning
# USAGE: menu "Biiig whoopsie!" --yesno "Are you sure?"; echo $ANSWER
# USAGE: menu "Choose a letter" --radiolist a A on b B off; echo $ANSWER
menu() {
  ANSWER="$(
    dialog \
      --clear --no-collapse --output-fd 1 \
      --backtitle "$MENU_TITLE" --title "$@"
  )"
}

# Says "ok" is a string matches a config option exactly, otherwise "off"
# USAGE: is role client # => on
# USAGE: is role server # => off
is() { [[ "$(get "$1")" == "$2" ]] && echo on || echo off; }

# Says "ok" is a string is included in a config option, otherwise "off"
# USAGE: has wifi_hacks defaults # => on
# USAGE: has wifi_hacks disabled-name # => off
has() { [[ "$(get "$1")" =~ "$2" ]] && echo on || echo off; }

#
# Menus
#
dialog_review() {
  menu "$BTRFS/srv/secure/config.json $UNSAVED" \
    --textbox "$CONFIG" 16 40 \
    || :
}

dialog_role() {
  menu "Change Role" \
    --radiolist "Choose role:" 12 45 6 \
    c "Client (default, not special)" "$(is role client)" \
    s "Server (needs Ethernet cable)" "$(is role server)" \
    || :

  case "$ANSWER" in
    c) set role client ;;
    s) set role server ;;
  esac
}

dialog_name() {
  menu "Change Name" \
    --inputbox "Enter name (tl-xxxx):" 8 40 "$(get hostname)" \
    || :

  if [[ -n "$ANSWER" ]]; then
    set hostname "$ANSWER"
  fi
}

dialog_wifi() {
  menu "WiFi Setup" \
    --radiolist "Choose a network" 14 45 6 \
    1 "TechLit Africa" "$(is wifi_name "TechLit Africa")" \
    2a "TechLit Vim" "$(is wifi_name "TechLit Vim")" \
    2b "TechLit Emacs" "$(is wifi_name "TechLit Emacs") " \
    4a "TechLit Vim Yank" "$(is wifi_name "TechLit Vim Yank")" \
    4b "TechLit Vim Paste" "$(is wifi_name "TechLit Vim Paste")" \
    4c "TechLit Emacs Mark" "$(is wifi_name "TechLit Emacs Mark")" \
    4d "TechLit Emacs Point" "$(is wifi_name "TechLit Emacs Point")" \
    || :

  set wifi_password empowerwatoto

  case "$ANSWER" in
    1) set wifi_name "TechLit Africa" ;;
    2a) set wifi_name "TechLit Vim" ;;
    2b) set wifi_name "TechLit Emacs" ;;
    4a) set wifi_name "TechLit Vim Yank" ;;
    4b) set wifi_name "TechLit Vim Paste" ;;
    4c) set wifi_name "TechLit Emacs Mark" ;;
    4d) set wifi_name "TechLit Emacs Point" ;;
  esac
}

dialog_wifi_hacks() {
  local hacks=(defaults "System defaults" "$(has wifi_hacks defaults)")
  for dir in "$ROOT/hacks/wifi/"*; do
    local hack="${dir##*/}"
    hacks+=("$hack" "$(cat "$dir/more")" "$(has wifi_hacks "$hack")")
  done

  if menu "WiFi Hacks" --checklist "Choose WiFi hacks:" 20 60 6 "${hacks[@]}"; then
    set wifi_hacks "$ANSWER"
  fi
}

dialog_gpu_hacks() {
  local hacks=(defaults "System defaults" "$(has gpu_hacks defaults)")
  for dir in "$ROOT/hacks/gpu/"*; do
    local hack="${dir##*/}"
    hacks+=("$hack" "$(cat "$dir/more")" "$(has gpu_hacks "$hack")")
  done

  if menu "GPU Hacks" --checklist "Choose GPU hacks:" 20 60 6 "${hacks[@]}"; then
    set gpu_hacks "$ANSWER"
  fi
}

dialog_system_hacks() {
  local hacks=(defaults "System defaults" "$(has system_hacks defaults)")
  if [ "$(find "$ROOT/hacks/system/" -mindepth 1 -type d | wc -l)" -gt 0 ]; then
    for dir in "$ROOT/hacks/system/"*; do
      local hack="${dir##*/}"
      hacks+=("$hack" "$(cat "$dir/more")" "$(has system_hacks "$hack")")
    done
  fi

  if menu "System Hacks" --checklist "Choose System hacks:" 20 60 6 "${hacks[@]}"; then
    set system_hacks "$ANSWER"
  fi
}

dialog_apply() {
  if ! menu "Apply Changes" --yesno "Save changes and reboot?" 6 60; then
    return
  fi
  clear

  say "Saving changes..."
  echo "$(c "$CONFIG")"
  cat "$CONFIG" >"$BTRFS/@srv/secure/config.json"

  say "Restoring image and Configuring system..."
  run "$ROOT/bin/tl-img-restore" "$BTRFS" "$VERSION"

  while true; do
    echo "$(y Reboot now?) $(c '[Y/n]')"
    read -n1 -s -r x

    case "${x:-y}" in
      y | Y)
        run sudo reboot
        break
        ;;
      n | N) break ;;
    esac
  done

  exit 0
}

dialog_quit() {
  if ! menu "Quit" --yesno "Discard changes and quit?" 6 60; then
    return
  fi
  clear

  exit 0
}

dialog_main() {
  while true; do
    menu "Configuration Options" \
      --menu "Choose what to do:" 16 45 6 \
      r "Review Config $UNSAVED" \
      b "Change Role ($(get role))" \
      n "Change Name ($(get hostname))" \
      w "Change WiFi ($(get wifi_name))" \
      d "WiFi Hacks (advanced)" \
      g "GPU Hacks (advanced)" \
      s "System Hacks (advanced)" \
      a "Apply Changes (reboot)" \
      q "Quit (discard changes)"

    case "$ANSWER" in
      r) dialog_review ;;
      b) dialog_role ;;
      n) dialog_name ;;
      w) dialog_wifi ;;
      d) dialog_wifi_hacks ;;
      g) dialog_gpu_hacks ;;
      s) dialog_system_hacks ;;
      a) dialog_apply ;;
      q) dialog_quit ;;
      *) exit 1 ;;
    esac
  done
}

[[ "$0" = "${BASH_SOURCE[0]}" ]] && dialog_main
