#!/bin/bash

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

set -x
set -e

true "$0: START"

run_cmd() {
  [ -n "$TESTING_MODE" ] || TESTING_MODE=0
  if [ "$TESTING_MODE" -eq 1 ]; then
    set +x
    echo "$@"
  else
    "$@"
  fi
}

## This path to this script in the derivative-maker source code folder is help-steps/dm-build-official.
## Go to root of the source code folder.
## Only needed if one would 'cd ./help-steps' beforehand.
#run_cmd cd ..

true "INFO: 0: $0"

if [ "$CI" = "true" ]; then
  true "INFO: Skipping test if folder ~/.ssh exists on CI."
else
  run_cmd test -d ~/.ssh
fi

## Optional testing of docker on CI.
if [ "$CI" = "true" ]; then
  ## Minimal test only for now.
  sudo --non-interactive -- ./docker/derivative-maker-docker-setup
  ./docker/derivative-maker-docker-run --build-step 1100_sanity-tests --target raw --flavor internal
fi

## Ordered as follows for the following reasons:
## - 1) Build '--flavor kicksecure-lxqt' because building ISO, which is newer,
##      therefore more prone to build issues. Error out quicker is better.
## - 2) Build '--flavor whonix-gateway-lxqt' because it is required to be able to
##      run dm-prepare-release due to unified ova files.
## - 3) Build '--flavor whonix-workstation-lxqt' because it is the most
##   complex, because of downloading Tor Browser as well as when used with
##   '--target windows', because:
##     - *_prepare-build-machine downloads VirtualBox-*-Win.exe
##     - dm-prepare-release builds Whonix Windows Installer
## - 4) Build CLI flavors because the least likely to have build issues.
if [ "$CI" = "true" ]; then
  ## TODO
  ## cross-building is too slow. Hits GitHub 6 hours maximum time.
  ## Can be overwritten in './help-steps/dm-build-official-one'.
  architecture=arm64
  build_args+=(--remote-derivative-packages true)

  ## Build fewer flavors on CI to save build time.
  ## - Specifically cross-builds (using AMD64 to build ARM64) is hitting GitHub CI timeout.
  ## - It is unlikely that building an LXQt flavor would succeed while the CLI flavor would fail.
#   [ -n "$flavors_list" ] || flavors_list=(
#     kicksecure-lxqt
#     whonix-gateway-lxqt
#     whonix-workstation-lxqt
#   )
  [ -n "$flavors_list" ] || flavors_list=(
    kicksecure-cli
  )
else
  [ -n "$flavors_list" ] || flavors_list=(
    kicksecure-lxqt
    kicksecure-cli
    whonix-gateway-lxqt
    whonix-workstation-lxqt
    whonix-gateway-cli
    whonix-workstation-cli
  )
fi

build_upload_noninteractive=true
export build_upload_noninteractive

dist_build_redistributable=true
export dist_build_redistributable

if [ "$dist_build_redistributable" = "true" ]; then
  build_args+=(--repo true)
  build_args+=(--tb closed)
fi

if printf '%s\n' "$@" | grep -- "remote-derivative-packages true" &>/dev/null; then
  remote_derivative_packages=true
fi

if printf '%s\n' "$build_args" | grep -- "remote-derivative-packages true" &>/dev/null; then
  remote_derivative_packages=true
fi

if [ "$remote_derivative_packages" = "true" ]; then
  ## Skip upload of debug images.
  rsync_cmd="true simulate-only"
  export rsync_cmd
fi

## If $architecture is unset, use build machine architecture.
[ -n "$architecture" ] || architecture="$(dpkg --print-architecture)"
build_args+=(--arch "$architecture")

multi_target_args=()

case $architecture in
  amd64)
    ## '--target virtualbox'
    ## Build VirtualBox ova. (amd64 for Windows, Linux, Mac)
    multi_target_args+=("--target" "virtualbox")
    multi_target_args+=("--target" "qcow2")
  ;;
  arm64)
    ## Build VirtualBox ova. (arm64 for Mac M1, M2 and maybe Linux.)
    #multi_target_args+=("--target" "virtualbox")
    #multi_target_args+=("--target" "qcow2")
    ## Only on arm64 for Mac M1, M2.
    multi_target_args+=("--target" "utm")
    ## Tor Browser is not yet available at time of writing for ARM64.
    build_args+=(--tb open)
  ;;
  *)
    ## '--target qcow2' might be the most universal.
    multi_target_args+=("--target" "qcow2")
  ;;
esac

## multi_target_args comment:
## Cannot mix,
## * 1) '--target iso', and,
## * 2) "${multi_target_args[@]}"
## because no ISO should be build for Whonix-Gateway, Whonix-Workstation.
## (Maybe in the future for Whonix-Host.)
## The ISO should only be built for Kicksecure-LXQt for now.

for flavor_item in "${flavors_list[@]}"; do
  ## Not yet using multi_target_args as the sanity test for Whonix-Gateway ISO would complain that the VMs
  ## have not been built yet.
  run_cmd ./build-steps.d/*_sanity-tests "${build_args[@]}" --target windows "${multi_target_args[@]}" --flavor "$flavor_item" "$@"
done

## Use both,
## * 1) '--target iso', and,
## * 2) "${multi_target_args[@]}"
## for prepare-build-machine, because additional dependencies are required for building the ISO.
run_cmd ./build-steps.d/*_prepare-build-machine "${build_args[@]}" --target iso --target windows "${multi_target_args[@]}" --flavor internal "$@"

run_cmd ./build-steps.d/*_cowbuilder-setup "${build_args[@]}" --target iso --target windows "${multi_target_args[@]}" --flavor internal "$@"
run_cmd ./build-steps.d/*_local-dependencies "${build_args[@]}" --target iso --target windows "${multi_target_args[@]}" --flavor internal "$@"

export dist_build_raw_base_image_create=true
## '--flavor internal' would lead to variable dist_build_hostname being unset.
## Therefore using '--flavor kicksecure-cli' to create a raw base image.
## '--target iso' must not be used because ISO is nowadays created using live-build, not create-raw-image.
## create-raw-image would do nothing if using '--target iso'.
run_cmd ./build-steps.d/*_create-raw-image "${build_args[@]}" "${multi_target_args[@]}" --flavor kicksecure-cli "$@"
unset dist_build_raw_base_image_create

## '--target iso' is required to download calamares from backports.
run_cmd ./build-steps.d/*_create-debian-packages "${build_args[@]}" --target iso "${multi_target_args[@]}" --flavor internal "$@"

## Fast. No need to skip.
#SKIP_SCRIPTS+=" sanity-tests "

SKIP_SCRIPTS+=" prepare-build-machine "
SKIP_SCRIPTS+=" cowbuilder-setup "
## Using cached_binary_image_raw_file instead because we will set dist_build_use_cached_raw_base_image=true.
## Variable cached_binary_image_raw_file will result in create-raw-image simply making a copy of the exiting raw image.
#SKIP_SCRIPTS+=" create-raw-image "
SKIP_SCRIPTS+=" local-dependencies "
SKIP_SCRIPTS+=" create-debian-packages "
export SKIP_SCRIPTS

dist_build_use_cached_raw_base_image=true
export dist_build_use_cached_raw_base_image

## Build and dm-prepare-release.
for flavor_item in "${flavors_list[@]}"; do
  case $flavor_item in
    kicksecure-lxqt)
      ## For now, create an ISO only for Kicksecure LXQt.
      ## Not for Kicksecure CLI.
      ## Not yet for Whonix.
      true "INFO: ISO build flavor."
      run_cmd ./derivative-maker "${build_args[@]}" --target iso --flavor "$flavor_item" "$@"
      ;;
    *)
      true "INFO: Non-ISO build flavor."
      ;;
  esac

  run_cmd ./derivative-maker "${build_args[@]}" "${multi_target_args[@]}" --flavor "$flavor_item" "$@"
done

## Same source code for all of the following: LXQt vs CLI and Kicksecure vs Whonix.
run_cmd dm-prepare-release --target source --flavor "kicksecure-lxqt" "$@"
run_cmd dm-upload-images --target source --flavor "kicksecure-lxqt" "$@"
run_cmd dm-upload-images --target source --flavor "whonix-workstation-lxqt" "$@"

if [ "$architecture" = "amd64" ]; then
  ## Also build the Whonix-Windows-Installer.
  run_cmd dm-prepare-release --target windows --flavor whonix-workstation-lxqt
  run_cmd dm-upload-images --target windows --flavor whonix-workstation-lxqt
fi

## Uploading.
for flavor_item in "${flavors_list[@]}"; do
  if printf '%s\n' "$flavor_item" | grep -- "gateway" &>/dev/null; then
    ## Not needed for gateway due to unified images.
    continue
  fi

  case $flavor_item in
    kicksecure-lxqt)
      true "INFO: ISO build flavor."
      run_cmd dm-upload-images "${build_args[@]}" --target iso --flavor "$flavor_item" "$@"
      ;;
    *)
      true "INFO: Non-ISO build flavor."
      ;;
  esac

  ## Cannot use "${multi_target_args[@]}" here, because
  ## help-steps/variables variable dist_server_with_upload_location_list is does not support multiple "--target"'s.
  for ((i=0; i<${#multi_target_args[@]}; i+=2)); do
    target_arg="${multi_target_args[i]}"
    target_value="${multi_target_args[i+1]}"
    run_cmd dm-upload-images "${build_args[@]}" $target_arg $target_value --flavor "$flavor_item" "$@"
  done
done

true "$0: END"
