#!/usr/bin/env bash
set -euo pipefail
source "$SHELLOPS_DIR/.envrc"
import "$SHELLOPS_DIR/lib/xplat/api.sh"
import "$SHELLOPS_DIR/lib/zigbuild/api.sh"
import "$SHELLOPS_DIR/lib/tarball/api.sh"

USAGE="$(cat <<EOF
Cross-compiles release binaries for all configured platform/arch targets,
strips debug symbols, and bundles into tarballs.

Expects zig and cargo-zigbuild to already be installed (declare them in
ops.lock and run \`shell/install\` first).

Usage: action rust build-release --bin <name> [--bin <name2> ...] --version <version> [options] [-- cargo-flags...]

Options:
  --bin <name>       Binary to build and package. Repeatable; first is the tarball name.
  --version <ver>    Release version for tarball naming (required).
  --outdir <dir>     Output directory for tarballs. Defaults to ./dist.
  -h, --help         Show this help text.

Everything after -- is forwarded to cargo zigbuild (e.g. --no-default-features).
EOF
)"

function main() {
  local bin_names=() version="" outdir="./dist"
  local cargo_flags=()

  parse_args bin_names version outdir cargo_flags "$@"
  validate_args bin_names "$version"

  local primary_name="${bin_names[0]}"
  local triples
  triples="$(xplat_build_triples)"

  local build_dir
  build_dir="$(mktemp -d)"

  for bin_name in "${bin_names[@]}"; do
    zigbuild_build_all "$triples" --bin "$bin_name" "${cargo_flags[@]}"
    zigbuild_strip_all "$bin_name" "$triples"
    tarball_stage_all "$build_dir" "$triples" __cargo_release_path "$bin_name"
  done

  local artifacts_json
  artifacts_json="$(tarball_create_all "$build_dir" "$primary_name" "$version" "$outdir")"

  rm -rf "$build_dir"

  local artifact_paths=()
  mapfile -t artifact_paths < <(jq_get "$artifacts_json" '.[]')

  tarball_save_artifacts "$outdir" "${artifact_paths[@]}"
  log "wrote ${outdir}/artifacts.json"
}

function validate_args() {
  local -n _bin_names=$1
  local version="$2"

  if [[ ${#_bin_names[@]} -eq 0 ]]; then
    error "--bin is required"
    log "$USAGE"
    exit 1
  fi

  if [[ -z "$version" ]]; then
    error "--version is required"
    log "$USAGE"
    exit 1
  fi
}

function __cargo_release_path() {
  local triple="$1" bin_name="$2"
  echo "target/${triple}/release/${bin_name}"
}

function parse_args() {
  local -n _bins=$1 _version=$2 _outdir=$3 _cargo_flags=$4
  shift 4

  while [[ $# -gt 0 ]]; do
    case "$1" in
      -h|--help) log "$USAGE"; exit 0 ;;
      --bin) _bins+=("$2"); shift ;;
      --version) _version="$2"; shift ;;
      --outdir) _outdir="$2"; shift ;;
      --) shift; _cargo_flags=("$@"); return ;;
      -*)
        error "Unknown option: $1"
        exit 1
        ;;
    esac
    shift
  done
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  main "$@"
fi
