#!/bin/bash

ScriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"

if [[ ! -d "${ScriptDir}/pengwin-setup.d" ]]; then
  ScriptDir="$(dirname "${ScriptDir}")"
fi

SetupDir="${ScriptDir}/pengwin-setup.d"
export SetupDir

# shellcheck source=pengwin-setup.d/common.sh
source "${SetupDir}"/common.sh "$@"

declare CANCELLED
declare SKIP_UPDATES
declare JUST_UPDATE
declare REQUIRES_X
declare DIALOG_TYPE
declare OFF


rm -f "${HOME}"/.should-restart

# define functions

#######################################
# description
# Globals:
#   JUST_UPDATE
#   WSL2
# Arguments:
#  None
#######################################
function check_upgrades() {
  start_indeterminate_progress

  echo "Updating package database"

  # shellcheck disable=SC2155
  local debian_security_ok="$(cat /etc/apt/sources.list 2>&1 | grep -c "https://deb.debian.org/debian-security testing/updates")"
  if [[ ${debian_security_ok} != 0 ]]; then
    sudo sed -i 's$debian-security testing/updates$debian-security testing-security$g' /etc/apt/sources.list
  fi

  # shellcheck disable=SC2119
  update_packages

  if [[ -z ${WSL2} ]]; then
    # If WSL1 fix systemd upgrades
    cd /bin && sudo mv -f systemd-sysusers{,.org} && sudo ln -s echo systemd-sysusers && cd -
  fi

  # Check if there's any upgrades to pengwin-setup / pengwin-base
  echo "Running upgrade check..."
  # shellcheck disable=SC2155
  local upgrd_check="$(sudo apt-get upgrade --show-upgraded --assume-no | grep pengwin)"
  if [[ "${upgrd_check}" == *"pengwin"* ]]; then
    echo "Pengwin core package upgrades found"
    if (confirm --title "Upgrades Available" --yesno "Updates have been detected for Pengwin core packages. Would you like to update them? This is highly recommended." 10 91); then

      # Ensure that packages get updated without affecting other held packages like udev
      sudo apt-mark unhold pengwin-base pengwin-setup >/dev/null 2>&1
      upgrade_packages --allow-downgrades pengwin-base pengwin-setup

      # shellcheck disable=SC2119
      update_packages
    fi
  elif [[ ${JUST_UPDATE} ]]; then
    upgrade_packages
  fi

  if [[ -z ${WSL2} ]]; then
    # If WSL1 fix systemd upgrades
    cd /bin && sudo mv -f systemd-sysusers{,.org} && sudo ln -s echo systemd-sysusers && cd -
  fi

  # Check for .dist-upgrade file in /etc/apt and inform user dist-upgrade available if so
  if [[ -f "/etc/apt/.dist-upgrade" ]]; then
    echo "Distribution upgrade flag noticed! Alerting user"
    if (confirm --title "Upgrade Available" --yesno "A distribution upgrade is available. In addition to regular package upgrades, this may also install / remove packages. Would you like to continue?\n\nTo run a non-automated distribution upgrade and see package changes, or to perform this in your own time, run 'sudo apt-get dist-upgrade'" 12 90); then
      sudo rm /etc/apt/.dist-upgrade
      sudo apt-get dist-upgrade -y
      sudo apt-get autoremove -y
      touch "${HOME}"/.should-restart
    fi
  fi

  if [[ -z ${WSL2} ]]; then
    # If WSL1 fix systemd upgrades
    cd /bin && sudo mv -f systemd-sysusers{,.org} && sudo ln -s echo systemd-sysusers && cd -
  fi

  if [[ -z ${WSL2} ]]; then
    # If WSL1 we patch libQt5Core.so
    sudo strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 >/dev/null 2>&1
  else
    if [[ $( dpkg-query -s "iproute2" 2>/dev/null | grep -c "Version: 5\.8.*" ) != 0 ]]; then
      sudo apt-mark unhold iproute2
      sudo apt-get install -q -y iproute2
    fi

  fi

  if [[ $(id | grep -c irc) == 0 ]]; then
    sudo /usr/sbin/usermod -aG irc "$(whoami)"
  fi

  stop_indeterminate_progress
}

#######################################
# description
# Arguments:
#  None
#######################################
function welcome_prompt() {
  message --title "Welcome to Pengwin" --msgbox "Thank you for supporting sustainable independent open source development.\n\nPengwin comes with a core set of useful packages pre-installed, such as curl, git, and wslu.\n\npengwin-setup allows you to install additional hand-curated selections for Pengwin and configure optional WSL-specific settings.\n\nMany more packages are available via the apt package manager and optional pip, npm, and RubyGems package managers." 17 80
}

#######################################
# description
# Arguments:
#  None
#######################################
function continue_prompt() {
  if (confirm --title "Continue setup?" --yesno "Would you like to continue pengwin-setup?" 8 45); then
    echo "Starting pengwin-setup."
  else
    echo "Exiting pengwin-setup."
    echo "You may run the script again any time by running: $ pengwin-setup"
    exit 0
  fi
}

#######################################
# description
# Globals:
#   CMD_MENU_OPTIONS
#   HOME
#   WIN_CUR_VER
#   WSL_DISTRO_NAME
# Arguments:
#  None
#######################################
function bye_message() {
  if [[ -f "${HOME}"/.should-restart ]]; then
    local should_restart=0
    rm -f "${HOME}"/.should-restart
  fi

  if [[ ${WIN_CUR_VER} -ge 17763 && ${should_restart} ]]; then
    message --title "Setup is complete." --msgbox "This window will be closed to apply the changes in the environment.\nPlease start Pengwin again \n\nYou may rerun pengwin-setup any time by typing: $ pengwin-setup\n\nYou may open a browser link to get help any time by typing: $ pengwin-help" 14 80

    if [[ ${#CMD_MENU_OPTIONS[*]} == 0 ]]; then #No automated installation
      wsl.exe --terminate "${WSL_DISTRO_NAME:-WLinux}"
    fi
  elif [[ ${should_restart} ]]; then
    message --title "Setup is complete." --msgbox "Please close this window and start Pengwin again to apply the changes in the environment.\n\nYou may rerun pengwin-setup any time by typing: $ pengwin-setup\n\nYou may open a browser link to get help any time by typing: $ pengwin-help" 14 80
  else
    message --title "Setup is complete." --msgbox "You may rerun pengwin-setup any time by typing: $ pengwin-setup\n\nYou may open a browser link to get help any time by typing: $ pengwin-help" 10 80
  fi
}

# main menu
function install_menu() {
  # shellcheck disable=SC2155,SC2086
  local menu_choice=$(

    menu --title "pengwin-setup" "${DIALOG_TYPE}" "\nHand-curated add-ons [ENTER to confirm]:" 0 0 0  \
      "AIUTILS" "Install AI tools and assistants" ${OFF}  \
      "EDITORS" "Install text editors neovim, emacs, or Visual Studio Code${REQUIRES_X}" ${OFF}  \
      "GUI" "Install an X server or various other GUI applications" ${OFF}  \
      "MAINTENANCE" "Various maintenance tasks like home backup" ${OFF}  \
      "PROGRAMMING" "Install various programming languages support" ${OFF}  \
      "SERVICES" "Enable services support (systemd, SSH, rc.local)" ${OFF}  \
      "SETTINGS" "Change various settings in Pengwin" ${OFF}  \
      "TOOLS" "Install applications or servers" ${OFF}  \
      "UNINSTALL" "Uninstall applications and packages installed by pengwin-setup" ${OFF}

    # shellcheck disable=SC2188
    3>&1 1>&2 2>&3
  )

  echo "Selected:" "${menu_choice}"

  if [[ ${menu_choice} == "${CANCELLED}" ]]; then
    return
  fi

  local exit_status

  if [[ ${menu_choice} == *"AIUTILS"* ]]; then
    echo "AIUTILS"
    bash "${SetupDir}"/ai.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"EDITORS"* ]]; then
    echo "EDITORS"
    bash "${SetupDir}"/editors.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"GUI"* ]]; then
    echo "GUI"
    bash "${SetupDir}"/gui.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"MAINTENANCE"* ]]; then
    echo "MAINTENANCE"
    bash "${SetupDir}"/maintenance.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"PROGRAMMING"* ]]; then
    echo "PROGRAMMING"
    bash "${SetupDir}"/programming.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"SERVICES"* ]]; then
    echo "SERVICES"
    bash "${SetupDir}"/services.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"SETTINGS"* ]]; then
    echo "SETTINGS"
    bash "${SetupDir}"/settings.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"TOOLS"* ]]; then
    echo "TOOLS"
    bash "${SetupDir}"/tools.sh "$@"
    exit_status=$?
  fi

  if [[ ${menu_choice} == *"UNINSTALL"* ]]; then
    echo "UNINSTALL"
    bash "${SetupDir}"/uninstall.sh "$@"
    exit_status=$?
  fi

  if [[ ${exit_status} != 0 ]]; then
    if [[ ${NON_INTERACTIVE} ]]; then
      return "${exit_status}"
    fi

    install_menu "$@"
  fi
}

function show_help() {
  cat <<'EOF'
Usage: pengwin-setup [OPTIONS] [COMMANDS] [ACTIONS]

pengwin-setup is a configuration utility for the Pengwin Linux distribution on Windows Subsystem for Linux (WSL). This script allows for various setup, update, installation, and uninstallation tasks to be performed, with support for both interactive and automated modes.

Options:
  --help, -h                     Display this help message and exit.
  --debug, -d, --verbose, -v     Run in debug/verbose mode, displaying detailed command execution output.
  -y, --yes, --assume-yes        Skip confirmations and proceed with default answers to prompts.
  --noupdate                     Skip the update step before showing the setup.
  --norebuildicons               Skip rebuilding the start menu icons.
  -q, --quiet, --noninteractive  Run in non-interactive mode, skipping confirmations and prompts.
  --multiple                     Allow to select multiple installers at once. (previous pengwin-setup behavior)

Commands:
  update, upgrade                Just update packages without any other actions. Implies --yes and --noninteractive.

  autoinstall, install ACTIONS   Automatically install packages without prompts or updates. Implies --noupdate, --noninteractive, --yes, and --norebuildicons.

  uninstall, remove ACTIONS      Automatically uninstall packages without prompts or updates. Implies --noupdate, --noninteractive, --yes, and --norebuildicons.

  startmenu                      Regenerate the start menu icons. Implies --noupdate, --noninteractive, and --yes.

Actions to be used after install command:
  AIUTILS                        AI tools: COPILOT-CLI, COPILOT-VIM.

  EDITORS                        Available editors: CODE, EMACS, NEOVIM, MSEDIT.

  GUI                            GUI-related options: CONFIGURE, DESKTOP, GPU, NLI, GUILIB, HIDPI, TERMINAL, SYNAPTIC, WINTHEME, WSLG.

  CONFIGURE                      Configuration options: DISPLAY, STARTMENU, VCXSRV, X410.

  GPU                            GPU settings: GPU_ACCEL_ENABLE, GPU_ACCEL_DISABLE.

  DESKTOP                        Desktop environments: XFCE.

  TERMINAL                       Terminal options: WINTERM, WSLTTY, TILIX, GTERM, XFTERM, TERMINATOR, KONSO.

  PROGRAMMING                    Programming languages and environments: C++, DOTNET, GO, JAVA, JETBRAINS, JOOMLA, LATEX, NIM, NODEJS, PYTHONPI, RUBY, RUST.

  NODEJS                         Node.js tools: NVERMAN, NVM, LATEST, LTS.

  PYTHONPI                       Python-related tools: PYENV, PYTHONPIP, POETRY.

  SERVICES                       Services management: LAMP, RCLOCAL, SSH, SYSTEMD.

  LAMP                           LAMP MySQL (MariaDB) versions: BUILTIN, 10.6, 10.7, 10.8, 10.9.

  SETTINGS                       System settings: EXPLORER, COLORTOOL, LANGUAGE, MOTD, SHELLS.

  SHELLS                         Shell options: BASH-RL, CSH, FISH, ZSH.

  TOOLS                          Additional tools: HOMEBREW, CLOUDCLI.

  CLOUDCLI                       Cloud CLI tools: TERRAFORM, KUBERNETES.

Examples:
  pengwin-setup --verbose update                Update packages with detailed output.
  pengwin-setup install GUI HIDPI               Configures HiDPI support without user interaction.
  pengwin-setup install PROGRAMMING PYTHONPI    Access Python-related programming options.

For more information, visit the Pengwin GitHub repository with the command pengwin-help.

EOF
}

### Main
if [[ ${SHOW_HELP} ]]; then
  show_help
  exit 0
fi

if [[ ${JUST_UPDATE} ]]; then
  check_upgrades
  exit 0
fi

welcome_prompt
continue_prompt

if [[ ! ${SKIP_UPDATES} ]]; then
  check_upgrades
fi

# Ensure our packages are held to prevent odd situation of
# being updated while running other operations from pengwin-setup
# install menu
echo "Holding pengwin-base & pengwin-setup to ensure no changes while operating"
sudo apt-mark hold pengwin-base pengwin-setup >/dev/null 2>&1

sudo apt-mark unhold libc6 >/dev/null 2>&1

install_menu "$@"

# Unhold our packages
echo "Unholding pengwin-base & pengwin-setup"
sudo apt-mark unhold pengwin-base pengwin-setup >/dev/null 2>&1

bye_message
exit 0
