#!/bin/bash

## Copyright (C) 2012 - 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

true "INFO: Currently running script: ${BASH_SOURCE[0]} $*"

MYDIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" && pwd )"
cd -- "$MYDIR"

## XXX: hardcoded path
source /usr/libexec/helper-scripts/strings.bsh
source "$HOME/derivative-maker/help-steps/pre"
source "$HOME/derivative-maker/help-steps/variables"

show_files() {
   local file_name_item
   for file_name_item in "${dist_build_files_to_upload[@]}"; do
      if [ -z "$file_name_item" ]; then
         continue
      fi

      test -f "$file_name_item"

      upload_file_list+=("${file_name_item}")
      upload_file_list+=("${file_name_item}.asc")

      if printf '%s\n' "${file_name_item}.sig" | grep dist-installer ; then
         upload_file_list+=("${file_name_item}.sig")
      else
         if test -f "${file_name_item}.sig" ; then
            upload_file_list+=("${file_name_item}.sig")
         fi
      fi

      upload_file_list+=("${file_name_item}.torrent")
      upload_file_list+=("${file_name_item}.torrent.asc")
      upload_file_list+=("${file_name_item}.torrent.sig")
      upload_file_list+=("${file_name_item}.sha512sums")
      upload_file_list+=("${file_name_item}.sha512sums.asc")
      upload_file_list+=("${file_name_item}.sha512sums.sig")
   done

   true "File list:"
   printf '%s\n' "${upload_file_list[@]}"

   local upload_file_item
   for upload_file_item in "${upload_file_list[@]}"; do
      test -f "$upload_file_item"
   done
}

upload_files() {
   if [ "$dist_build_installer_dist" = "true" ]; then
      dist_server_with_upload_location_item_with_version_maybe="${dist_server_with_upload_location_item}/"
   else
      dist_server_with_upload_location_item_with_version_maybe="${dist_server_with_upload_location_item}/${dist_build_version}/"
   fi
   true "dist_server_with_upload_location_item_with_version_maybe: $dist_server_with_upload_location_item_with_version_maybe"

   if [ ! "${build_upload_noninteractive:-}" = "true" ]; then
      true "${cyan}INFO: Press any enter to continue.${reset}"
      read -r temp
   fi

   rsync_dry_run_maybe="--dry-run"

   attempts_counter="0"
   attempts_max="100"

   while true; do
      attempts_counter="$(( attempts_counter + 1 ))"
      ## Linear backoff: each retry waits 5 s longer than the
      ## previous one (5 s, 10 s, 15 s, ..., capping at 5 s * 100 =
      ## 500 s ~= 8 min on the final retry, ~7 h cumulative over
      ## attempts_max=100). Computed from attempts_counter rather
      ## than mutating sleep_seconds, so the value cannot leak
      ## (and grow forever) across calls to upload_files.
      sleep_seconds="$(( attempts_counter * 5 ))"

      if [ "$rsync_dry_run_maybe" = "--dry-run" ]; then
         true "${cyan}INFO: --dry-run only...${reset}"
      else
         true "${cyan}INFO: uploading...${reset}"
      fi

      ## Test if DNS is functional.
      ## Sometimes 'rsync' fails to resolve DNS but running 'nslookup' beforehand fixes it.
      ## Overrule with '|| true' as the failure would be handled below by 'rsync'.
      for dist_server_with_upload_location_item in $dist_server_with_upload_location_list; do
         nslookup "$dist_server_with_upload_location_item" || true
      done

      rsync_exit_code="0"
      $rsync_cmd \
         $rsync_dry_run_maybe \
         $rsync_opts \
         "${upload_file_list[@]}" \
         "$dist_server_with_upload_location_item_with_version_maybe" \
         || { rsync_exit_code="$?" ; true; };

      if [ "$rsync_exit_code" = "0" ]; then
         if [ "$rsync_dry_run_maybe" = "--dry-run" ]; then
            if [ ! "${build_upload_noninteractive:-}" = "true" ]; then
               true "${cyan}INFO: Press any enter to continue.${reset}"
               read -r temp
            fi
            rsync_dry_run_maybe=""
            continue
         fi
         break
      fi

      if [ "$attempts_counter" -ge "$attempts_max" ]; then
         error "${bold}${red}ERROR: Upload failed.${reset}"
         ## Allow to ignore the error such as after fixing the internet connection.
         continue
      fi

      sleep "$sleep_seconds" || true

   done
}

main() {
   if [ ! "$dist_build_image_upload_supported" = "true" ]; then
      if [ "${CI:-}" = "true" ]; then
         true "upload support for this --target is not yet implemented."
         exit 0
      else
         error "upload support for this --target is not yet implemented."
      fi
   fi

   if [ "$dist_build_version" = "" ]; then
      error "Variable dist_build_version is empty."
   fi

   if [ "$dist_server_with_upload_location_list" = "" ]; then
      error "Variable dist_server_with_upload_location_list is empty."
   fi

   show_files

   for dist_server_with_upload_location_item in $dist_server_with_upload_location_list ; do
      upload_files
   done

   true
}

main
