#!/bin/bash

## Copyright (C) 2019 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

#set -x
set -o errexit
set -o nounset
set -o pipefail
set -o errtrace
shopt -s inherit_errexit
shopt -s shift_verbose
export LC_ALL=C

benchmark_start=0

## Thanks to perreal for the convertsecs function.
## http://stackoverflow.com/a/12199798
## NOTE: If uncommenting for some reason, use is_whole_number from strings.bsh
## to verify the safety of ${1}
#convertsecs() {
#   local h m s
#   ((h="${1}/3600"))
#   ((m="(${1}%3600)/60"))
#   ((s="${1}%60"))
#   printf "%02d:%02d:%02d\n" "$h" "$m" "$s"
#}

## We need raw seconds as output for some comparisons, so we can't use
## helper-scripts' benchmark.bsh.
benchmark_time_start() {
   benchmark_start="${SECONDS}"
}

benchmark_time_end() {
   benchmark_took_seconds="$(( SECONDS - benchmark_start ))"
}

variables() {
   vmname="Whonix-Gateway-LXQt"
   user_name="user"
   password=""

   vboxmanage_cmd="VBoxManage --nologo"
   vboxheadless_cmd="vboxheadless"

   vm_wait_for_vm_start_timeout=60
   vm_wait_for_vm_shutdown_timeout=20

   # shellcheck disable=SC2206 # ${vboxmanage_cmd} is meant to word-split
   vboxmanage_sudo_wrapper=(
      ${vboxmanage_cmd}
      guestcontrol "${vmname}" run
      --username "${user_name}"
      --password "${password}"
      --wait-stdout --wait-stderr
      --exe /usr/libexec/helper-scripts/sudo-askpass-wrapper
      --
      apt/sudo-askpass-wrapper
   )
}

vm_is_running_test() {
   running_vms_list="$(${vboxmanage_cmd} list runningvms)" || true

   ## example running_vms_list:
   ##   "Whonix-Workstation-LXQt" {c504a345-8217-4954-8864-a5270a661b11}
   ## A previous version word-split $running_vms_list, which broke
   ## any VM name that contained spaces (the quoted name token was
   ## split across multiple words). Match the full quoted name +
   ## the following ` {uuid}` separator with grep -F instead.
   vm_running=false
   if grep -F -- "\"${vmname}\" {" <<< "${running_vms_list}" >/dev/null ; then
      vm_running=true
   fi
}

wait_vm_shutdown() {
   benchmark_time_start
   while true ; do
      vm_is_running_test
      benchmark_time_end
      if [ "${vm_running}" = "false" ]; then
         printf '%s\n' "INFO: VM shutdown took ${benchmark_took_seconds} seconds."
         break
      fi
      if [ "${benchmark_took_seconds}" -ge "${vm_wait_for_vm_shutdown_timeout}" ]; then
         printf '%s\n' "ERROR: VM shutdown longer than ${vm_wait_for_vm_shutdown_timeout} seconds." >&2
         exit 1
      fi
      sleep 2
   done
}

error_out_if_vm_is_running() {
   vm_is_running_test
   if [ "${vm_running}" = "true" ]; then
      printf '%s\n' "ERROR: VM not expected to be still running!" >&2
      exit 1
   fi
}

start_vm() {
   ## Does not exist but more debug output.
   #$vboxheadless_cmd --startvm "$vmname"

   ${vboxmanage_cmd} startvm "${vmname}" --type headless
}

power_off_vm_audit() {
   ${vboxmanage_cmd} controlvm "${vmname}" poweroff
}

power_off_vm_ignore() {
   ${vboxmanage_cmd} controlvm "${vmname}" poweroff &>/dev/null || true
}

acpipowerbutton_vm() {
   VBoxManage controlvm "${vmname}" acpipowerbutton
}

vm_guest_control_cmd() {
   ${vboxmanage_cmd} guestcontrol "${vmname}" run --username "${user_name}" --password "${password}" --wait-stdout --wait-stderr --exe "$@"
}

wait_for_vm() {
   printf '%s\n' "INFO: Waiting for VM guestcontrol to get ready."
   benchmark_time_start
   while true ; do
      benchmark_time_end
      if vm_guest_control_cmd "/bin/ls" &>/dev/null ; then
         printf '%s\n' "INFO: VM was ready after ${benchmark_took_seconds} seconds."
         break
      fi
      if [ "${benchmark_took_seconds}" -ge "${vm_wait_for_vm_start_timeout}" ]; then
         printf '%s\n' "ERROR: VM took longer than ${vm_wait_for_vm_start_timeout} seconds to start." >&2
         exit 1
      fi
      sleep 2
   done
}

whonix_developer_repository_enable() {
   "${vboxmanage_sudo_wrapper[@]}" repository-dist --verbose --enable --repository developers
}

# kill_apt() {
#    pid="$($vboxmanage_sudo_wrapper pgrep apt)"
#
#    $vboxmanage_sudo_wrapper kill -s sigterm "$pid"
# }

apt_update() {
   "${vboxmanage_sudo_wrapper[@]}" dpkg --configure -a

   "${vboxmanage_sudo_wrapper[@]}" apt-get update
}

install_packages() {
   "${vboxmanage_sudo_wrapper[@]}" apt-get --yes install lkrg tirdad

   "${vboxmanage_sudo_wrapper[@]}" apt-get --yes autoremove
}

snapshot_vm_create() {
   #VBoxManage snapshot Whonix-Gateway-LXQt list --machinereadable

   #SnapshotName="before-dev-upgrade"
   #SnapshotUUID="23f0703b-79e7-436b-9a5e-67e8cc6aace0"
   #CurrentSnapshotName="before-dev-upgrade"
   #CurrentSnapshotUUID="23f0703b-79e7-436b-9a5e-67e8cc6aace0"
   #CurrentSnapshotNode="SnapshotName"

   snapshot_name="before-dev-upgrade"

   ## Do not create another snapshot with the same name.
   snapshot_list_output="$(${vboxmanage_cmd} snapshot "${vmname}" list --machinereadable)"
   if printf '%s\n' "${snapshot_list_output}" | grep -- "${snapshot_name}" >/dev/null 2>/dev/null; then
      return 0
   fi

   ${vboxmanage_cmd} snapshot "${vmname}" take "${snapshot_name}"
}

snapshot_vm_restore() {
   snapshot_name="before-dev-upgrade"
   ${vboxmanage_cmd} snapshot "${vmname}" restore "${snapshot_name}"
}

variables

# power_off_vm_ignore
# error_out_if_vm_is_running
# start_vm
# wait_for_vm

#kill_apt
apt_update
install_packages

# acpipowerbutton_vm
# wait_vm_shutdown

#$vboxmanage_cmd guestcontrol "$vmname" run --username "$user_name" --password changeme --wait-stdout --wait-stderr --exe "/bin/ls" -- ls/arg0 vmtest arg1 "a test2"
