#!/usr/bin/env bash

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly ROOT
readonly RESULTS="${ROOT}/results"
readonly IMAGE="serein-test-05-mutation"

if [[ "${RESULTS}" != "${ROOT}/results" ]]; then
  echo "refusing to clear an unexpected results directory" >&2
  exit 65
fi

cd "${ROOT}"

milliseconds() {
  perl -MTime::HiRes=time -e 'printf "%.0f\n", time * 1000'
}

capture() {
  local name="$1"
  local expected_exit="$2"
  shift 2

  local directory="${RESULTS}/${name}"
  local started
  local finished
  local actual_exit

  mkdir -p "${directory}"
  {
    printf '%q' "$1"
    for argument in "${@:2}"; do
      printf ' %q' "${argument}"
    done
    printf '\n'
  } >"${directory}/command.txt"

  started="$(milliseconds)"
  set +e
  "$@" >"${directory}/output.txt.tmp" 2>&1
  actual_exit=$?
  set -e
  finished="$(milliseconds)"

  sed -E -e 's/[[:space:]]+$//' -e '${/^$/d;}' \
    "${directory}/output.txt.tmp" >"${directory}/output.txt"
  rm "${directory}/output.txt.tmp"

  {
    printf 'expected_exit_code=%s\n' "${expected_exit}"
    printf 'exit_code=%s\n' "${actual_exit}"
    printf 'duration_ms=%s\n' "$((finished - started))"
  } >"${directory}/metadata.txt"

  if [[ ${actual_exit} -ne ${expected_exit} ]]; then
    echo "FAILED: ${name} exited ${actual_exit}; expected ${expected_exit}" >&2
    return 1
  fi

  printf '%-34s exit %s as expected\n' "${name}" "${actual_exit}"
}

in_container() {
  docker run --rm \
    --volume "${RESULTS}:/experiment/results" \
    "${IMAGE}" \
    "$@"
}

mutation_run() {
  local suite="$1"

  in_container php -d memory_limit=512M vendor/bin/infection \
    src/CatalogueResponseTranslator.php \
    --configuration="infection-${suite}.json5" \
    --with-uncovered \
    --min-msi=100 \
    --min-covered-msi=100 \
    --threads=1 \
    --show-mutations=max \
    --no-progress
}

rm -rf \
  "${RESULTS}/comparison" \
  "${RESULTS}/environment" \
  "${RESULTS}/setup" \
  "${RESULTS}/strong" \
  "${RESULTS}/weak"
mkdir -p \
  "${RESULTS}/strong/reports" \
  "${RESULTS}/weak/reports"

capture setup/build 0 docker build --tag "${IMAGE}" .
capture environment/php 0 in_container php --version
capture environment/xdebug 0 \
  in_container php -r 'echo phpversion("xdebug"), PHP_EOL;'
capture environment/packages 0 \
  in_container composer show --locked --direct --no-ansi
capture environment/composer-audit 0 \
  in_container composer audit --locked --no-ansi --no-interaction

capture weak/phpunit 0 \
  in_container php -d memory_limit=512M vendor/bin/phpunit \
  --configuration suites/weak/phpunit.xml
capture strong/phpunit 0 \
  in_container php -d memory_limit=512M vendor/bin/phpunit \
  --configuration suites/strong/phpunit.xml

capture weak/mutation-run 1 mutation_run weak
capture strong/mutation-run 1 mutation_run strong

rm -rf "${RESULTS}/weak/tmp" "${RESULTS}/strong/tmp"

capture comparison 0 in_container php compare.php

echo "Evidence retained in ${RESULTS}"
