#!/bin/bash

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

## This script is executed on the host with the purpose of setting up
## required volume directories and executing the docker run command with any given arguments.

## TODO:
## amd64 images build under a Debian 12 Docker image end up with no BIOS bootloader due to lsblk malfunctioning #348
## https://github.com/grml/grml-debootstrap/issues/348
## related:
## lsblk fails to report partition type UUIDs within a privileged Debian 12 container #50304
## https://github.com/moby/moby/issues/50304

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

HOST_USER="$(id -u)"
DOCKER_USER="user"
COMMAND="./derivative-maker"
DOCKER_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" && pwd )"
SOURCE_VOLUME="$( dirname -- "${DOCKER_DIR}" )"
BINARY_VOLUME="$HOME/binary_mnt"
CACHER_VOLUME="$HOME/approx_cache_mnt"
KEY_VOLUME="$HOME/.key_mnt"
IMG="derivative-maker/derivative-maker-docker"
[[ -v CI ]] || CI=""

if [ "$CI" = "true" ]; then
  sudo_options_maybe+=("--non-interactive")
fi
[[ -v sudo_options_maybe ]] || sudo_options_maybe=()

sudo "${sudo_options_maybe[@]}" test -d /usr

declare orig_ref exit_code
orig_ref=""
exit_code=""

print_usage() {
  cat -- << EOF
  Usage: $0 [ options ]

  General Options:
    -b|--build-step  : build-step in derivative-maker/build-steps.d/
    -c|--custom      : custom command or shell compliant command chain
    --binary-mount   : Changes the binary artifact directory
    --cacher-mount   : Changes the package cache directory
    --key-mount      : Changes the keystore directory
    -h|--help        : print usage dialog
EOF
}

volume_prepare() {
  declare -a -- VOLUMES

  VOLUMES=(
    "${CACHER_VOLUME}" "101:102" "770"
    "${BINARY_VOLUME}" "${HOST_USER}:${HOST_USER}" "770"
    "${KEY_VOLUME}" "${HOST_USER}:${HOST_USER}" "700"
  )

  while (( ${#VOLUMES[@]} > 0 )); do
    if [ ! -d "${VOLUMES[0]}" ]; then
      mkdir --parents -- "${VOLUMES[0]}"
      sudo "${sudo_options_maybe[@]}" -- chown --recursive -- "${VOLUMES[1]}" "${VOLUMES[0]}"
      sudo "${sudo_options_maybe[@]}" -- chmod --recursive -- "${VOLUMES[2]}" "${VOLUMES[0]}"
    fi

    VOLUMES=("${VOLUMES[@]:3}")
  done
}

build_docker_image() {
  if [ -z "$(docker images --quiet -- "${IMG}" 2> /dev/null)" ]; then
    sudo \
    "${sudo_options_maybe[@]}" \
    -- \
      docker \
        build \
        --tag \
        "${IMG}:latest" \
        "${DOCKER_DIR}"
  fi
}

## TODO: Consider what should happen when derivative-maker-docker-run is run without arguments.

while true; do
  case "${1:-}" in
    -b|--build-step)
      COMMAND="build-steps.d/${2}"
      shift 2
      ;;
    -c|--custom)
      COMMAND="${2}"
      shift 2
      ;;
    --binary-mount)
      BINARY_VOLUME="${2}"
      shift 2
      ;;
    --cacher-mount)
      CACHER_VOLUME="${2}"
      shift 2
      ;;
    --key-mount)
      KEY_VOLUME="${2}"
      shift 2
      ;;
    -h|--help)
      print_usage
      exit 0
      ;;
    --)
      shift
      break
      ;;
    *)
      break
      ;;
  esac
done

## "Update" the repository to the current ref without pulling any additional
## remote code. This acts as a sanity check, and as a trust-on-first-use
## mechanism.
exit_code='0'

# orig_ref="$(git symbolic-ref HEAD)" || exit_code="$?"
# if [ "${exit_code}" != '0' ]; then
#   orig_ref="$(git rev-parse HEAD)" || error 'Cannot get head commit ID!'
# else
#   # shellcheck disable=SC2001
#   orig_ref="$(sed 's?^refs/heads/??' <<< "${orig_ref}")"
# fi

## TODO: Should docker do this?
## fetch/merge git submodules
#"${SOURCE_VOLUME}/derivative-update" --update-only

build_docker_image

volume_prepare

sudo "${sudo_options_maybe[@]}" -- modprobe -a loop dm_mod

sudo \
  "${sudo_options_maybe[@]}" \
  -- \
    docker \
      run \
      --name derivative-maker-docker \
      --interactive \
      --tty \
      --rm \
      --privileged \
      --env 'flavor_meta_packages_to_install=' \
      --env 'install_package_list=' \
      --env 'DERIVATIVE_APT_REPOSITORY_OPTS=' \
      --volume "${SOURCE_VOLUME}:/home/${DOCKER_USER}/derivative-maker" \
      --volume "${BINARY_VOLUME}:/home/${DOCKER_USER}/derivative-binary" \
      --volume "${CACHER_VOLUME}:/var/cache/approx-derivative-maker" \
      --volume "${KEY_VOLUME}:/home/${DOCKER_USER}/.gnupg" \
      "${IMG}" \
        sudo \
          --non-interactive \
          --preserve-env \
          -u "${DOCKER_USER}" \
          -- \
            "/usr/bin/derivative-maker-docker-start" "${COMMAND}" "${@}"
