#!/bin/bash

## wiki-vbox-version-update - Find new versions of VirtualBox and update the
##   links in the wiki accordingly.

set -o errexit
set -o nounset
set -o errtrace
set -o pipefail

true "INFO: Currently running script: $BASH_SOURCE $@"

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

if [ "$MYDIR" = "/usr/bin" ]; then
   true "INFO: Run from: /usr/bin"
   ## XXX: hardcoded path
   derivative_maker_source_code_dir="$HOME/derivative-maker"
else
   true "INFO: Run from: source code folder"
   derivative_maker_source_code_dir="$(cd -- "$MYDIR" && cd -- "../../../../../" && pwd)"
fi

## required by: make-helper-one.bsh
cd "$derivative_maker_source_code_dir"

command -v mw-fetch >/dev/null
command -v mw-edit >/dev/null
command -v stecho >/dev/null
command -v stsponge >/dev/null
command -v overwrite >/dev/null

declare -A url_cache
declare -A wiki_cache

get_url_cached () {
   local url

   url="${1:-}"
   [ -z "${url}" ] && return 1

   if [ -z "${url_cache["${url}"]:-}" ]; then
      url_cache["${url}"]="$(2>/dev/null scurl "${url}")"
   fi

   url_content="${url_cache["${url}"]}"
}

get_wiki_page_cached () {
   local wiki_page cache_id tmpfile

   wiki_page="${1:-}"
   [ -z "${wiki_page}" ] && return 1

   tmpfile="$(mktemp)"

   cache_id="${WIKI_URL} - ${wiki_page}"

   if [ -z "${wiki_cache["${cache_id}"]:-}" ]; then
      mw-fetch "${WIKI_URL}" "${wiki_page}" "${tmpfile}"
      wiki_cache["${cache_id}"]="$(cat -- "${tmpfile}")"
      safe-rm -- "${tmpfile}"
   fi

   wiki_content="${wiki_cache["${cache_id}"]}"
}

# TODO: It might be more lightweight to use release-monitoring.org to detect
#   the latest VirtualBox release.
# get_latest_version-virtualbox () {
#    get_url_cached 'https://release-monitoring.org/api/v2/packages/?name=Virtualbox'
#    jq '.items[] | select ( contains({distribution: "Windows"}) ) | .version' <<< "${url_content}"
# }

extract_url () {
   local content regex line regex_result

   content="${1:-}"
   regex="${2:-}"
   [ -z "${content}" ] && return 1
   [ -z "${regex}" ] && return 1

   while read -r line; do
      if [[ "${line}" =~ ${regex} ]]; then
         regex_result="$(perl -p -e "s/.*(${regex}).*/\1/" <<< "${line}")"
      fi
   done <<< "${content}"

   stecho "${regex_result}"
}

get_url_from_page () {
   local dl_page release_regex line result

   dl_page="${1:-}"
   release_regex="${2:-}"
   [ -z "${dl_page}" ] && return 1
   [ -z "${release_regex}" ] && return 1

   get_url_cached "${dl_page}"
   readarray -t result < <(extract_url "${url_content}" "${release_regex}")

   if [ "${#result[@]}" != '1' ]; then
      1>&2 stecho 'WARNING - more than one URL found for download!'
   elif [ -z "${result[0]}" ]; then
      1>&2 stecho 'WARNING - no URL found!'
   fi

   func_result="${result[0]}"
}

get_url_from_wiki () {
   local wiki_page release_regex content result

   wiki_page="${1:-}"
   release_regex="${2:-}"
   [ -z "${wiki_page}" ] && return 1
   [ -z "${release_regex}" ] && return 1

   get_wiki_page_cached "${wiki_page}"
   readarray -t result < <(extract_url "${wiki_content}" "${release_regex}")

   if [ "${#result[@]}" != '1' ]; then
      1>&2 stecho 'WARNING - more than one URL found for download!'
   elif [ -z "${result[0]}" ]; then
      1>&2 stecho 'WARNING - no URL found!'
   fi

   func_result="${result[0]}"
}

replace_wiki_string () {
   local wiki_page orig_string new_string cache_id tmpfile

   wiki_page="${1:-}"
   orig_string="${2:-}"
   new_string="${3:-}"
   [ -z "${wiki_page}" ] && return 1
   [ -z "${orig_string}" ] && return 1
   [ -z "${new_string}" ] && return 1

   cache_id="${WIKI_URL} - ${wiki_page}"
   wiki_content="${wiki_cache["${cache_id}"]}"
   [ -z "${wiki_content}" ] && return 1

   tmpfile="$(mktemp)"
   append-once "${tmpfile}" "${wiki_content}"
   str_replace "${orig_string}" "${new_string}" "${tmpfile}"
   wiki_content="$(cat -- "${tmpfile}")"
   wiki_cache["${cache_id}"]="${wiki_content}"

   safe-rm -- "${tmpfile}"
}

# TODO: Templates for future work
# get_latest_version-tor-browser () {
#    true
# }
#
# get_latest_version-tor-browser-alpha () {
#    true
# }
#
# get_current_version-tor-browser () {
#    true
# }
#
# get_current_version-tor-browser-alpha () {
#    true
# }

save_cached_page_to_wiki () {
   local wiki_page tmpfile

   wiki_page="${1:-}"
   [ -z "${wiki_page}" ] && return 1

   tmpfile="$(mktemp)"

   get_wiki_page_cached "${wiki_page}"
   append-once "${tmpfile}" "${wiki_content}"

   mw-edit "${WIKI_URL}" "${tmpfile}" "${wiki_page}"
   ## TODO
   ## XXX: hardcoded
   #mw-edit 'https://www.whonix.org/w' "${tmpfile}" "${wiki_page}"

   safe-rm -- "${tmpfile}"
}

declare kicksecure_wiki_vbox_page vbox_download_page vbox_win_regex vbox_macos_intel64_regex vbox_macos_arm64_regex
kicksecure_wiki_vbox_page='Template:VirtualBox_Host_Software_Installation'
vbox_download_page='https://www.virtualbox.org/wiki/Downloads'
vbox_win_regex='https:\/\/download.virtualbox.org\/virtualbox\/.*\/VirtualBox-.*Win\.exe'
vbox_macos_intel64_regex='https:\/\/download.virtualbox.org\/virtualbox\/.*\/VirtualBox-.*OSX.dmg'
vbox_macos_arm64_regex='https:\/\/download.virtualbox.org\/virtualbox\/.*\/VirtualBox-.*macOSArm64.dmg'

WIKI_URL='https://www.kicksecure.com/w'

main () {
   local vbox_win_latest vbox_macos_intel64_latest vbox_macos_arm64_latest vbox_win_current vbox_macos_intel64_current vbox_macos_arm64_current update_done sha_link_root sha_link_full

   update_done='false'
#    if [ ! -v WIKI_API_USER_NAME ]; then
#       stecho "ERROR: No username provided! Please ensure WIKI_API_USER_NAME is set in the environment."
#       exit 1
#    elif [ ! -v WIKI_API_USER_PASS ]; then
#       stecho "ERROR: No user password provided! Please ensure WIKI_API_USER_PASS is set in the environment."
#       exit 1
#    fi

   get_url_from_page "${vbox_download_page}" "${vbox_win_regex}";   vbox_win_latest="${func_result}"
   get_url_from_page "${vbox_download_page}" "${vbox_macos_intel64_regex}"; vbox_macos_intel64_latest="${func_result}"
   get_url_from_page "${vbox_download_page}" "${vbox_macos_arm64_regex}"; vbox_macos_arm64_latest="${func_result}"
   get_url_from_wiki "${kicksecure_wiki_vbox_page}" "${vbox_win_regex}";   vbox_win_current="${func_result}"
   get_url_from_wiki "${kicksecure_wiki_vbox_page}" "${vbox_macos_intel64_regex}"; vbox_macos_intel64_current="${func_result}"
   get_url_from_wiki "${kicksecure_wiki_vbox_page}" "${vbox_macos_arm64_regex}"; vbox_macos_arm64_current="${func_result}"

   if [ "${vbox_win_latest}" != "${vbox_win_current}" ]; then
      replace_wiki_string "${kicksecure_wiki_vbox_page}" "${vbox_win_current}" "${vbox_win_latest}"
      update_done='true'
   fi
   if [ "${vbox_macos_intel64_latest}" != "${vbox_macos_intel64_current}" ]; then
      replace_wiki_string "${kicksecure_wiki_vbox_page}" "${vbox_macos_intel64_current}" "${vbox_macos_intel64_latest}"
      update_done='true'
   fi
   if [ "${vbox_macos_arm64_latest}" != "${vbox_macos_arm64_current}" ]; then
      replace_wiki_string "${kicksecure_wiki_vbox_page}" "${vbox_macos_arm64_current}" "${vbox_macos_arm64_latest}"
      update_done='true'
   fi

   if [ "${update_done}" = 'true' ]; then
      save_cached_page_to_wiki "${kicksecure_wiki_vbox_page}"
   fi

   sha_link_root="$(dirname -- "${vbox_win_latest}")"
   ## example sha_link_full
   ## https://download.virtualbox.org/virtualbox/7.2.2/SHA256SUMS
   sha_link_full="${sha_link_root}/SHA256SUMS"

   ## vbox_win_latest example:
   ## https://download.virtualbox.org/virtualbox/7.2.2/VirtualBox-7.2.2-170484-Win.exe
   overwrite "${derivative_maker_source_code_dir}/windows/virtualbox/download.txt" "${vbox_win_latest}"
   ## Useful as audit trail. Not functionally required.
   overwrite "${derivative_maker_source_code_dir}/windows/virtualbox/weblink_SHA256SUMS" "${sha_link_full}"

   scurl "${sha_link_full}" | stsponge "${derivative_maker_source_code_dir}/windows/virtualbox/SHA256SUMS"

   true "SUCCESS"
}

main "$@"
