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

if (( $# < 2 )); then
  printf 'usage: %s high|low COMMAND [ARG...]\n' "$0" >&2
  exit 64
fi

class=$1
shift

case "$class" in
  high)
    slice=interactive.slice
    cpu_weight=10000
    io_weight=10000
    command=("$@")
    ;;
  low)
    # Build work carries a memory ceiling, so it goes through confine.sh — the one
    # mechanism that never hands back an unbounded command.
    export CONFINE_CPU_WEIGHT=1 CONFINE_IO_WEIGHT=1
    exec "$(dirname "${BASH_SOURCE[0]}")/confine.sh" build \
      nice -n 19 ionice -c 3 chrt --idle 0 "$@"
    ;;
  *)
    printf 'invalid priority class: %s\n' "$class" >&2
    exit 64
    ;;
esac

if [[ "${PRIORITY_NO_SYSTEMD:-0}" != 1 ]] && command -v systemd-run >/dev/null 2>&1 \
    && command -v systemctl >/dev/null 2>&1 \
    && systemctl --user show-environment >/dev/null 2>&1; then
  systemd_properties=(
    -p CPUWeight="$cpu_weight"
  )
  user_cgroup=""
  if command -v systemctl >/dev/null 2>&1; then
    user_cgroup="$(systemctl --user show --property=ControlGroup --value 2>/dev/null || true)"
  fi
  if [[ -n "$user_cgroup" && -e "/sys/fs/cgroup${user_cgroup}/io.weight" ]]; then
    systemd_properties+=(-p IOWeight="$io_weight")
  fi
  systemd_environment=(-E "PATH=$PATH")
  for name in BUILD_SLOT_HELD CPU_GUARD_ACTIVE BUILD_SLOT_DIR BUILD_SLOTS \
    BUILD_SLOT_FIXED BUILD_SLOT_FLOOR BUILD_SLOT_TIMEOUT BUILD_SLOT_STAT \
    AGENT_BUILD_SCOPE_ACTIVE; do
    if [[ -v "$name" ]]; then
      systemd_environment+=(-E "$name=${!name}")
    fi
  done
  exec systemd-run --user --scope --quiet \
    --slice="$slice" \
    --same-dir \
    "${systemd_environment[@]}" \
    "${systemd_properties[@]}" \
    -- "${command[@]}"
fi

printf '[priority-run] user systemd unavailable; using scheduler fallback\n' >&2
exec "${command[@]}"
