#!/usr/bin/env bash

###############################################################################
# $1: the ctest directory
# $2: whether to run the test (TEST) or generate ref data (GENERATE_REF)
# $3: the current test's name
# $4: the current test's parameter file
# $5: the current test's sequence file (if any)
# $6: generation at which to resume evolution
# $7: end generation
# $8: the aevol_create binary (used to generate the test's input)
# $9: the aevol_run binary to be tested
###############################################################################

CTEST_DIR=$1
TEST_OR_GENERATE=$2
CUR_TEST_FULL_NAME=$3
CUR_TEST_PARAM_FILE=$4
CUR_TEST_SEQ_FILE=$5
CHECKPOINT_GENER=$6
END_GENER=$7
AEVOL_CREATE=$8
AEVOL_RUN=$9

CUR_TEST_DIR=$CTEST_DIR/$CUR_TEST_FULL_NAME
CUR_TEST_INPUT_DIR="test_input"

# cd into the test's directory (create if not exists)
if [ ! -e "$CUR_TEST_DIR" ]; then mkdir "$CUR_TEST_DIR" || exit 1; fi
cd "$CUR_TEST_DIR" || exit 1

# If we're generating the reference data, we first need to generate the input of the test (if any)
if [ "$TEST_OR_GENERATE" = "GENERATE_REF" ]; then
  # make sure there is an empty $CUR_TEST_INPUT_DIR and cd into it
  rm -rf "${CUR_TEST_INPUT_DIR:?}/"
  mkdir "$CUR_TEST_INPUT_DIR" || exit 1
  cd "$CUR_TEST_INPUT_DIR" || exit 1

  # run $AEVOL_CREATE
  CMD="$AEVOL_CREATE $CUR_TEST_PARAM_FILE"
  echo "running $CMD from $PWD..."
  $CMD || exit 1

  # cd back into the test's directory
  cd "$CUR_TEST_DIR" || exit 1
fi

if [ "$TEST_OR_GENERATE" != "TEST" ] && [ "$TEST_OR_GENERATE" != "GENERATE_REF" ]; then
  echo "passed \"$TEST_OR_GENERATE\"; should be either \"TEST\" or \"GENERATE_REF\""
  exit 1
fi


if [ "$TEST_OR_GENERATE" = "TEST" ]; then
  # -------------------------------------------------- INITIAL RUN
  INITIAL_RUN_DIR="ref"
  # make sure there is an empty $INITIAL_RUN_DIR
  rm -rf "${INITIAL_RUN_DIR:?}/"
  mkdir "$INITIAL_RUN_DIR" || exit 1

  # copy test_input data in $INITIAL_RUN_DIR
  cp -r $CUR_TEST_INPUT_DIR/* $INITIAL_RUN_DIR/

  # cd into $INITIAL_RUN_DIR
  cd "$INITIAL_RUN_DIR" || exit 1

  # run initial aevol_run
  CMD="$AEVOL_RUN -p -1 -b 0 -e $END_GENER"
  echo "running $CMD from $PWD..."
  $CMD || exit 1

  # cd back into the test's directory
  cd "$CUR_TEST_DIR" || exit 1


  # -------------------------------------------------- RUN FROM CHECKPOINT
  # make sure there is an empty $RUN_FROM_CHECKPOINT_DIR
  RUN_FROM_CHECKPOINT_DIR="res"
  rm -rf "${RUN_FROM_CHECKPOINT_DIR:?}/"
  mkdir "$RUN_FROM_CHECKPOINT_DIR" || exit 1

  # copy checkpoint in $RUN_FROM_CHECKPOINT_DIR
  echo "copying checkpoint into $RUN_FROM_CHECKPOINT_DIR..."
  cp -v $INITIAL_RUN_DIR/last_gener.txt $RUN_FROM_CHECKPOINT_DIR/ || exit 1
  cp -rv $INITIAL_RUN_DIR/*"$CHECKPOINT_GENER"* $RUN_FROM_CHECKPOINT_DIR/
  cp -rv $INITIAL_RUN_DIR/stats $RUN_FROM_CHECKPOINT_DIR/ || exit 1
  mkdir $RUN_FROM_CHECKPOINT_DIR/tree || exit 1
  cp -rv $INITIAL_RUN_DIR/tree/*"$CHECKPOINT_GENER"* $RUN_FROM_CHECKPOINT_DIR/tree/
  mkdir $RUN_FROM_CHECKPOINT_DIR/checkpoints || exit 1
  cp -rv $INITIAL_RUN_DIR/checkpoints/*"$CHECKPOINT_GENER"* $RUN_FROM_CHECKPOINT_DIR/checkpoints/ || exit 1

  # cd into $RUN_FROM_CHECKPOINT_DIR
  cd "$RUN_FROM_CHECKPOINT_DIR" || exit 1

  # run initial aevol_run
  CMD="$AEVOL_RUN -p -1 -b $CHECKPOINT_GENER -e $END_GENER"
  echo "running $CMD from $PWD..."
  $CMD || exit 1

  # cd back into the test's directory
  cd "$CUR_TEST_DIR" || exit 1


  # -------------------------------------------------- CHECK RESULTS
  fail=0

  # for each regular file in ref that has either no timestamp or that is stamped at or after $CHECKPOINT_GENER,
  # diff it with its res counterpart
  for reffile in \
      $(find $INITIAL_RUN_DIR -type f  | \
          awk 'match($0,/[0-9]+/,number)&&number[0]>='$CHECKPOINT_GENER'||!match($0,/[0-9]+/)'); do
    # Strip reffile of the first dir level ("$INITIAL_RUN_DIR")
    file=${reffile#$INITIAL_RUN_DIR/} # Shell Parameter Expansion
    echo "checking file $file"
    if ! diff -q "$INITIAL_RUN_DIR/$file" "$RUN_FROM_CHECKPOINT_DIR/$file"; then
      fail=1
    fi
  done

  if test $fail -ne 0; then exit 1; fi
fi

exit 0
