#!/usr/bin/env bash
set -euo pipefail
umask 077

root="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
program="$root/libexec/program"
manifest="$root/lispex-topaz-vm-provider.json"
artifact="$root/topaz-artifact.json"

if [[ "${1:-}" != "run" ]]; then
  echo "usage: lispex-topaz-vm run --request <request.json> --bytecode <program.lpxbc> [--input <input.datum>] --result <result.json>" >&2
  exit 64
fi
shift

result=""
request=""
bytecode=""
input_path=""
while [[ $# -gt 0 ]]; do
  case "$1" in
    --request)
      [[ $# -ge 2 ]] || { echo "missing --request value" >&2; exit 64; }
      request="$2"
      shift 2
      ;;
    --bytecode)
      [[ $# -ge 2 ]] || { echo "missing --bytecode value" >&2; exit 64; }
      bytecode="$2"
      shift 2
      ;;
    --input)
      [[ $# -ge 2 ]] || { echo "missing --input value" >&2; exit 64; }
      input_path="$2"
      shift 2
      ;;
    --result)
      [[ $# -ge 2 ]] || { echo "missing --result value" >&2; exit 64; }
      result="$2"
      shift 2
      ;;
    *)
      echo "unknown option: $1" >&2
      exit 64
      ;;
  esac
done

[[ -n "$request" && -n "$bytecode" && -n "$result" ]] || {
  echo "request, bytecode, and result paths are required" >&2
  exit 64
}
[[ ! -e "$result" && ! -L "$result" ]] || {
  echo "result path already exists: $result" >&2
  exit 73
}
[[ -x "$program" && -f "$manifest" && -f "$artifact" ]] || {
  echo "installed provider is incomplete" >&2
  exit 70
}

sha256() { shasum -a 256 -- "$1" | awk '{print $1}'; }
temporary="${result}.tmp.$$"
workspace="${result}.work.$$"
[[ ! -e "$temporary" && ! -L "$temporary" ]] || {
  echo "temporary result path already exists: $temporary" >&2
  exit 73
}
[[ ! -e "$workspace" && ! -L "$workspace" ]] || {
  echo "temporary workspace path already exists: $workspace" >&2
  exit 73
}
mkdir -m 700 -- "$workspace"
mkdir -m 700 -- "$workspace/fixtures"
cleanup() {
  rm -f -- "$temporary"
  rm -rf -- "$workspace"
}
trap cleanup EXIT
cp -- "$request" "$workspace/fixtures/request.json"
cp -- "$bytecode" "$workspace/fixtures/program.lpxbc"
if [[ -n "$input_path" ]]; then
  cp -- "$input_path" "$workspace/fixtures/input.datum"
fi

arguments=(
  provider-run
  --request fixtures/request.json
  --bytecode fixtures/program.lpxbc
  --actual-provider-manifest-sha256 "$(sha256 "$manifest")"
  --actual-topaz-artifact-sha256 "$(sha256 "$artifact")"
  --actual-executable-sha256 "$(sha256 "$program")"
  --actual-target "aarch64-apple-darwin"
  --actual-host "native"
)
if [[ -n "$input_path" ]]; then
  arguments+=(--input fixtures/input.datum)
fi

(cd "$workspace" && "$program" "${arguments[@]}") > "$temporary"
ln -- "$temporary" "$result"
cleanup
trap - EXIT
