#!/usr/bin/env bash

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly ROOT
readonly RESULTS="${ROOT}/results"
readonly IMAGE="serein-ddd-03-node"
cd "${ROOT}"

milliseconds() { perl -MTime::HiRes=time -e 'printf "%.0f\n", time * 1000'; }
capture() {
  local name="$1" expectation="$2"
  shift 2
  local directory="${RESULTS}/${name}" started finished exit_code
  mkdir -p "${directory}"
  printf '%q ' "$@" | sed -E 's/[[:space:]]+$//' >"${directory}/command.txt"
  printf '\n' >>"${directory}/command.txt"
  started="$(milliseconds)"
  set +e
  "$@" >"${directory}/output.txt.tmp" 2>&1
  exit_code=$?
  set -e
  finished="$(milliseconds)"
  sed -E -e 's/[[:space:]]+$//' -e '${/^$/d;}' "${directory}/output.txt.tmp" >"${directory}/output.txt"
  rm "${directory}/output.txt.tmp"
  printf 'expectation=%s\nexit_code=%s\nduration_ms=%s\n' "${expectation}" "${exit_code}" "$((finished - started))" >"${directory}/metadata.txt"
  [[ "${expectation}" == pass && ${exit_code} -eq 0 ]] || [[ "${expectation}" == fail && ${exit_code} -ne 0 ]]
}
mutation_case() {
  local name="$1" temporary source
  temporary="$(mktemp -d)"
  capture "mutations/${name}/generate" pass node mutate.mjs "${name}" "${temporary}"
  source="$(node -e "const fs=require('fs');console.log(JSON.parse(fs.readFileSync(process.argv[1])).source)" "${RESULTS}/mutations/${name}/generate/output.txt")"
  capture "diffs/${name}" fail diff -u --label "${source} (clean)" --label "${source} (${name})" "${ROOT}/${source}" "${temporary}/${source}"
  capture "negative/${name}" fail docker run --rm --volume "${temporary}:/candidate:ro" "${IMAGE}" node verify.mjs /candidate
  rm -rf "${temporary}"
}

rm -rf "${RESULTS}"
mkdir -p "${RESULTS}"
capture setup/build pass docker build --tag "${IMAGE}" .
capture environment/node pass docker run --rm "${IMAGE}" node --version
capture positive/tests pass docker run --rm "${IMAGE}" node --test tests/*.test.mjs
capture analysis/contract pass docker run --rm "${IMAGE}" node verify.mjs
capture analysis/comparison pass docker run --rm "${IMAGE}" node render-comparison.mjs
for mutation in \
  api-implies-customer-supplier ticket-implies-influence \
  meeting-implies-influence contract-test-implies-influence \
  unilateral-customer-supplier conformist-without-acceptance \
  conformist-with-contradiction separate-ways-access-denied \
  separate-ways-outage separate-ways-no-owner classify-target-state \
  global-team-label weighted-score missing-reversal-condition \
  orphan-evidence resolve-contradiction-attractively; do
  mutation_case "${mutation}"
done
capture sources/primary pass docker run --rm "${IMAGE}" node source-evidence.mjs
capture provenance/manifest pass docker run --rm "${IMAGE}" node source-manifest.mjs
capture verification/results pass docker run --rm --volume "${RESULTS}:/experiment/results:ro" "${IMAGE}" node verify-results.mjs
echo "DDD-03 evidence retained in ${RESULTS}"
