#!/usr/bin/env bash
set -Eeuo pipefail
command_name=${0##*/}
: "${TEST_MOCK_LOG:?TEST_MOCK_LOG must identify the isolated test log}"
allow_empty=${MOCK_ALLOW_EMPTY_INVOCATION:-}
printf '%q' "$command_name" >>"$TEST_MOCK_LOG"
for argument in "$@"; do printf ' %q' "$argument" >>"$TEST_MOCK_LOG"; done
printf '\n' >>"$TEST_MOCK_LOG"
if [[ $# == 3 && $1 == show && -n ${WG_MOCK_INTERFACE:-} && $2 == "$WG_MOCK_INTERFACE" && $3 == dump && -z ${WG_MOCK_DUMP_SEQUENCE_DIR:-} && -n ${WG_MOCK_DUMP_FILE:-} && -f $WG_MOCK_DUMP_FILE ]]; then
  if [[ -n ${WG_MOCK_DUMP_FAIL_ON_CALL:-} ]]; then
    dump_counter=${WG_MOCK_DUMP_FAIL_COUNTER_FILE:-${TEST_ROOT}/dump-counter}
    dump_calls=0; [[ -f $dump_counter ]] && read -r dump_calls <"$dump_counter"; ((dump_calls += 1)); printf '%s\n' "$dump_calls" >"$dump_counter"
    [[ $dump_calls != "$WG_MOCK_DUMP_FAIL_ON_CALL" ]] || exit 98
  fi
  cat -- "$WG_MOCK_DUMP_FILE"
  exit 0
fi
if [[ $# == 3 && $1 == show && -n ${WG_MOCK_INTERFACE:-} && $2 == "$WG_MOCK_INTERFACE" && $3 == dump && -n ${WG_MOCK_DUMP_SEQUENCE_DIR:-} ]]; then
  [[ ${WG_MOCK_DUMP_SEQUENCE_DIR} == "${TEST_ROOT}"/* && -d ${WG_MOCK_DUMP_SEQUENCE_DIR} && ! -L ${WG_MOCK_DUMP_SEQUENCE_DIR} ]] || exit 99
  sequence_counter=${WG_MOCK_DUMP_SEQUENCE_DIR}/counter
  [[ ! -L "$sequence_counter" && ( -f "$sequence_counter" || ! -e "$sequence_counter" ) ]] || exit 99
  sequence_number=0
  [[ -f "$sequence_counter" ]] && read -r sequence_number <"$sequence_counter"
  ((sequence_number += 1))
  printf '%s\n' "$sequence_number" >"$sequence_counter"
  sequence_file=${WG_MOCK_DUMP_SEQUENCE_DIR}/${sequence_number}
  [[ -f "$sequence_file" ]] && cat -- "$sequence_file" && exit 0
  printf 'Mock wg dump sequence exhausted\n' >&2
  exit 98
fi
if [[ $# == 3 && $1 == syncconf ]]; then
  [[ -n ${WG_MOCK_INTERFACE:-} && $2 == "$WG_MOCK_INTERFACE" ]] || { printf 'Mock wg wrong interface\n' >&2; exit 99; }
  if [[ ${WG_SYNC_FAIL_ONCE_FILE:-} && ! -e ${WG_SYNC_FAIL_ONCE_FILE} ]]; then
    : >"$WG_SYNC_FAIL_ONCE_FILE"
    printf 'Mock wg syncconf failure once\n' >&2
    exit 97
  fi
  if [[ -n ${WG_SYNC_FAIL_ON_CALL:-} ]]; then
    sync_counter=${WG_SYNC_FAIL_COUNTER_FILE:-${TEST_ROOT}/sync-counter}
    sync_calls=0; [[ -f $sync_counter ]] && read -r sync_calls <"$sync_counter"; ((sync_calls += 1)); printf '%s\n' "$sync_calls" >"$sync_counter"
    [[ $sync_calls != "$WG_SYNC_FAIL_ON_CALL" ]] || { printf 'Mock wg syncconf failure\n' >&2; exit 97; }
  fi
  [[ -f $3 && ! -L $3 && ${WG_SYNC_FAIL:-0} != 1 && -n ${TEST_ROOT:-} && $3 == "${TEST_ROOT}"/* ]] || { printf 'Mock wg syncconf failure\n' >&2; exit 97; }
  [[ $(stat -c '%a' -- "$3") == 600 ]] || { printf 'Mock wg syncconf unsafe mode\n' >&2; exit 97; }
  if [[ -n ${WG_SYNC_EXPECTED_STRIP:-} ]]; then
    [[ -f $WG_SYNC_EXPECTED_STRIP ]] || exit 97
    cmp -s -- "$3" "$WG_SYNC_EXPECTED_STRIP" || { printf 'Mock wg syncconf unexpected stripped content\n' >&2; exit 97; }
  fi
  if [[ -n ${WG_SYNC_READY_FIFO:-} ]]; then
    [[ ${WG_SYNC_READY_FIFO} == "${TEST_ROOT}"/* && -p ${WG_SYNC_READY_FIFO} && ${WG_SYNC_RELEASE_FIFO:-} == "${TEST_ROOT}"/* && -p ${WG_SYNC_RELEASE_FIFO} ]] || exit 99
    printf 'ready\n' >"$WG_SYNC_READY_FIFO"
    IFS= read -r _ <"${WG_SYNC_RELEASE_FIFO:?WG_SYNC_RELEASE_FIFO must be set}"
  fi
  exit 0
fi
if [[ -n "$allow_empty" && "$allow_empty" != "$command_name" ]]; then
  printf 'Unexpected mock invocation: %s does not allow empty calls for %s\n' "$command_name" "$allow_empty" >&2
  exit 99
fi
if [[ $# == 0 && "$allow_empty" == "$command_name" ]]; then
  exit 0
fi
printf 'Unexpected mock invocation: %s received arguments\n' "$command_name" >&2
exit 99
