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

usage() {
  cat <<'EOF'
Usage:
  run_rpki_client_from_local_tree.sh \
    --rpki-client-bin <path> \
    --mirror-root <local-rsync-mirror-root> \
    --tal-dir <dir> | --tal <file>... \
    --out-dir <path> \
    [--cache-dir <work-cache-dir>] \
    [--validation-time <RFC3339>] \
    [--real-rsync-bin <path>] \
    [--parser-workers <n>]

The input mirror is prepared by the caller. This script disables RRDP, points
rpki-client's rsync command at a local URI mapper, and fetches only from the
local filesystem tree.
EOF
}

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RPKI_CLIENT_BIN=""
CACHE_DIR=""
MIRROR_ROOT=""
OUT_DIR=""
TAL_DIR=""
VALIDATION_TIME=""
PARSER_WORKERS="${PARSER_WORKERS:-4}"
REAL_RSYNC_BIN="${REAL_RSYNC_BIN:-/usr/bin/rsync}"
TALS=()

while [[ $# -gt 0 ]]; do
  case "$1" in
    --rpki-client-bin) RPKI_CLIENT_BIN="$2"; shift 2 ;;
    --mirror-root) MIRROR_ROOT="$2"; shift 2 ;;
    --cache-dir) CACHE_DIR="$2"; shift 2 ;;
    --tal-dir) TAL_DIR="$2"; shift 2 ;;
    --tal) TALS+=("$2"); shift 2 ;;
    --out-dir) OUT_DIR="$2"; shift 2 ;;
    --validation-time) VALIDATION_TIME="$2"; shift 2 ;;
    --real-rsync-bin) REAL_RSYNC_BIN="$2"; shift 2 ;;
    --parser-workers) PARSER_WORKERS="$2"; shift 2 ;;
    -h|--help) usage; exit 0 ;;
    *) echo "unknown argument: $1" >&2; usage >&2; exit 2 ;;
  esac
done

[[ -n "$RPKI_CLIENT_BIN" && -n "$MIRROR_ROOT" && -n "$OUT_DIR" ]] || { usage >&2; exit 2; }
[[ -x "$RPKI_CLIENT_BIN" ]] || { echo "rpki-client binary not executable: $RPKI_CLIENT_BIN" >&2; exit 2; }
[[ -d "$MIRROR_ROOT" ]] || { echo "mirror root not found: $MIRROR_ROOT" >&2; exit 2; }
if [[ -z "$TAL_DIR" && "${#TALS[@]}" -eq 0 ]]; then
  echo "provide --tal-dir or at least one --tal" >&2
  exit 2
fi

mkdir -p "$OUT_DIR"
if [[ -z "$CACHE_DIR" ]]; then
  CACHE_DIR="$OUT_DIR/cache"
fi
mkdir -p "$CACHE_DIR" "$OUT_DIR/out"
chmod a+rwx "$OUT_DIR" "$CACHE_DIR" "$OUT_DIR/out"
WORK_DIR="$OUT_DIR/work"
PREPARED_TALS="$WORK_DIR/tals"
rm -rf "$WORK_DIR"
mkdir -p "$PREPARED_TALS"
PREPARE_TAL_ARGS=(--out-dir "$PREPARED_TALS" --summary "$OUT_DIR/prepared-tals.json")
if [[ -n "$TAL_DIR" ]]; then
  PREPARE_TAL_ARGS+=(--tal-dir "$TAL_DIR")
fi
for tal in "${TALS[@]}"; do
  PREPARE_TAL_ARGS+=(--tal "$tal")
done
python3 "$SCRIPT_DIR/prepare_tals.py" "${PREPARE_TAL_ARGS[@]}"

CLIENT_TAL_ARGS=()
while IFS= read -r tal; do
  CLIENT_TAL_ARGS+=(-t "$tal")
done < <(find "$PREPARED_TALS" -maxdepth 1 -type f -name '*.tal' | sort)

TIME_ARGS=()
if [[ -n "$VALIDATION_TIME" ]]; then
  epoch="$(python3 - <<'PY' "$VALIDATION_TIME"
from datetime import datetime, timezone
import sys
print(int(datetime.fromisoformat(sys.argv[1].replace("Z", "+00:00")).astimezone(timezone.utc).timestamp()))
PY
)"
  TIME_ARGS=(-P "$epoch")
fi

export CIR_MIRROR_ROOT="$(cd "$MIRROR_ROOT" && pwd)"
export REAL_RSYNC_BIN="$REAL_RSYNC_BIN"
export CIR_LOCAL_LINK_MODE=1

/usr/bin/time -v -o "$OUT_DIR/process-time.txt" \
  "$RPKI_CLIENT_BIN" \
  -R -e "$SCRIPT_DIR/cir-rsync-wrapper" -j -c -p "$PARSER_WORKERS" \
  "${TIME_ARGS[@]}" \
  "${CLIENT_TAL_ARGS[@]}" \
  -d "$CACHE_DIR" \
  "$OUT_DIR/out" >"$OUT_DIR/stdout.log" 2>"$OUT_DIR/stderr.log"

python3 "$SCRIPT_DIR/normalize_rp_outputs.py" --kind rpki-client --input "$OUT_DIR/out" --vrps-out "$OUT_DIR/vrps.normalized.txt" --vaps-out "$OUT_DIR/vaps.normalized.txt"
python3 "$SCRIPT_DIR/summarize_replay.py" --rp rpki-client --out-dir "$OUT_DIR" --summary "$OUT_DIR/summary.json"
echo "done: $OUT_DIR"
