#!/bin/bash

if test -n "$PLUMED_PREPEND_PATH" ; then
  PATH="$PLUMED_PREPEND_PATH:$PATH"
fi

export valgrind=env

for opt in ${*}
do
case "$opt" in
(--valgrind) valgrind="valgrind --leak-check=full --track-origins=yes" ;;
(*) echo error ; exit ;;
esac
done

{

date
echo "Running regtest in $(pwd)"

if [ "$valgrind" = valgrind ] ; then
echo "using valgrind"
fi

rm -fr tmp
mkdir tmp
cd tmp
cp -f ../* . 2>/dev/null

test -f config || {
  echo "FAILURE: config not found"
  exit 1
}

mpiprocs=0

plumed_needs=
plumed_modules=

plumed_language=c++

source ./config

for file in $extra_files
do
  cp -f ../$file .
done

echo "++ Test type: $type"
echo "++ Arguments: $arg"
echo "++ Processors: $mpiprocs"

mpi=env
plumed="${PLUMED_PROGRAM_NAME:-plumed}"

root=$($plumed --no-mpi info --root)

if test -z "$root" ; then
  echo "FAILURE: plumed executable not available"
  exit 1
fi

cd ../../../../
if [[ "${PWD}"/ != "$root" ]] ; then
echo "WARNING using plumed from $root"
fi
cd -


if ((mpiprocs>0)); then
mpi=""
if $plumed --no-mpi config -q mpiexec
then
  mpi="$($plumed --no-mpi config mpiexec)"
fi
if test -z "$mpi" ; then
  mpi="${PLUMED_MPIRUN:-mpirun}"
fi
mpi="$mpi -np $mpiprocs"

if ! $plumed config -q has mpi
then
    if [ "$TRAVIS" = true ] || [ "$GITHUB_ACTIONS" = true ] ; then
      if [ -z "$PLUMED_ALLOW_SKIP_ON_TRAVIS" ] ; then
        echo "NOT_APPLICABLE (MPI NOT INSTALLED)"
      else
        echo "SKIP_ON_TRAVIS found!"
      fi
    else
      echo "NOT_APPLICABLE (MPI NOT INSTALLED)"
    fi
  exit 0;
fi

else

plumed="$plumed --no-mpi"

fi

if ((mpiprocs>0)) && [[ "$valgrind" != "env" ]]
then
    if [ "$TRAVIS" = true ] || [ "$GITHUB_ACTIONS" = true ] ; then
      if [ -z "$PLUMED_ALLOW_SKIP_ON_TRAVIS" ] ; then
        echo "NOT_APPLICABLE (MPI cannot be used with valgrind)"
      else
        echo "SKIP_ON_TRAVIS found!"
      fi
    else
      echo "NOT_APPLICABLE (MPI cannot be used with valgrind)"
    fi
  exit 0;
fi

for need in $plumed_needs
do
  echo "Checking for $need"
  if ! $plumed config -q has $need
  then
    if [ "$TRAVIS" = true ] || [ "$GITHUB_ACTIONS" = true ] ; then
      if [ -z "$PLUMED_ALLOW_SKIP_ON_TRAVIS" ] ; then
        echo "NOT_APPLICABLE ($need NOT ENABLED)"
      else
        echo "SKIP_ON_TRAVIS found!"
      fi
    else
      echo "NOT_APPLICABLE ($need NOT ENABLED)"
    fi
    exit 0;
  fi
done

for module in $plumed_modules
do
  echo "Checking for $module"
  if ! $plumed config -q module $module
  then
    if [ "$TRAVIS" = true ] || [ "$GITHUB_ACTIONS" = true ] ; then
      if [ -z "$PLUMED_ALLOW_SKIP_ON_TRAVIS" ] ; then
        echo "NOT_APPLICABLE ($module MODULE NOT INSTALLED)"
      else
        echo "SKIP_ON_TRAVIS found!"
      fi
    else
      echo "NOT_APPLICABLE ($module MODULE NOT INSTALLED)"
    fi
    exit 0;
  fi
done

if type -t plumed_custom_skip 1>/dev/null ; then
  if plumed_custom_skip ; then
    if [ "$TRAVIS" = true ] || [ "$GITHUB_ACTIONS" = true ] ; then
      if [ -z "$PLUMED_ALLOW_SKIP_ON_TRAVIS" ] ; then
        echo "NOT_APPLIABLE (plumed_custom_skip)"
      else
        echo "SKIP_ON_TRAVIS found!"
      fi
    else
      echo "NOT_APPLIABLE (plumed_custom_skip)"
    fi
    exit 0;
  fi
fi

if $plumed --is-installed ; then
  export PLUMED_KERNEL="$root/../lib${PLUMED_PROGRAM_NAME:-plumed}Kernel.$($plumed info --soext)"
else
  export PLUMED_KERNEL="$root/src/lib/libplumedKernel.$($plumed info --soext)"
fi
if type -t plumed_regtest_before 1>/dev/null ; then
  plumed_regtest_before
fi

case "$type" in
(simplemd)
  test -f in || {
    echo "FAILURE: in file not present"
    exit 1
  }
  $mpi $valgrind $plumed simplemd < in > out 2> err
  ;;
(driver)
  $mpi $valgrind $plumed driver $arg > out 2> err
  ;;
(sum_hills)
  $mpi $valgrind $plumed sum_hills $arg > out 2> err
 ;;
(make)
  $plumed info --configuration > Makefile.conf
  $plumed --is-installed || ln -s "$root/src" plumed
  if test "$plumed_language" = fortran || test "$plumed_language" = fortran08 || test "$plumed_language" = c ; then
    cat <($plumed info --configuration) "$root/src/lib/Plumed.inc.shared" ../../../scripts/exe.make > Makefile 
  else
    cat <($plumed info --configuration) "$root/src/lib/Plumed.inc.static" ../../../scripts/exe.make > Makefile 
  fi
  if test "$plumed_language" = fortran || test "$plumed_language" = fortran08 ; then
    if make print-fortran | grep "FC=$" 1>/dev/null ; then
      echo "NOT_APPLICABLE (FC NOT FOUND)"
      exit 0
    else
      if test "$plumed_language" = fortran08 ; then
        cat > __test_fortran08.f90 << EOF
module test_fortran08_a
type b
contains
  final :: c
end type b
contains
  impure elemental subroutine c(x)
    type(b), intent(inout) :: x
  end subroutine c
end module test_fortran08_a
EOF
        if make test-fortran08 2>err | grep SUCCESS=YES 1> /dev/null ; then
          make exe-fortran08 1>out 2>err
        else
          echo "NOT_APPLICABLE (FC does not support f2008)"
          exit 0
        fi
      else
        make exe-fortran 1>out 2> err
      fi
    fi
  elif test "$plumed_language" = c || test "$plumed_language" = c11 ; then
    if test "$plumed_language" = c11 ; then
      cat > __test_c11.c << EOF
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ < 201112L
error
#endif
#else
error
#endif
int f(int a){
  return a;
}
EOF
      if make test-c11 2>err | grep SUCCESS=YES 1> /dev/null ; then
        make exe-c 1>out 2> err
      else
          echo "NOT_APPLICABLE (CC does not support c11)"
          exit 0
      fi
    else
      make exe-c 1>out 2> err
    fi
  else
    make exe 1>out 2> err
  fi
  $mpi $valgrind ./exe $arg >> out 2>> err
 ;;
(plumed)
  $mpi $valgrind $plumed $arg > out 2> err
  ;;
(python)
# make sure the right python module is in the path based on plumed root
  PYTHONPATH="$root/python:$PYTHONPATH" $($plumed config python_bin) $arg > out 2> err
  ;;
(*) echo "FAILURE: unknown test type" ; exit 1 ;;
esac
exitcode="$?"
if test $exitcode -ne 0 ; then
  echo "FAILURE: exit code $exitcode"
fi

if type -t plumed_regtest_after 1>/dev/null ; then
  plumed_regtest_after
fi

cat err


if ls *.reference > /dev/null
then
for file in *.reference ; do
  new="${file%.reference}"
  if test -f "$new" ; then
    ../../../scripts/fixzeroes.sh "$file"
    cp "$new" "$new.zfix"
    ../../../scripts/fixzeroes.sh "$new.zfix"
    DIFFOPT=""
# this is to enforce ASCII check
# I add this option since sometime on travis some of the diff files are not shown
# (files are thought to be binary for some reason)
# In this way, at least PLUMED native files (with fields) will be assumed to be
# ASCII and diff will be shown in the log
    test "$(head -c 10 "$file")" = "#! FIELDS " && DIFFOPT="-a"
    out="$(diff $DIFFOPT "$file" "$new.zfix")"
    test -n "$out" && {
      echo FAILURE
      echo "Diff for ${file%.reference}:"
      echo "$out"
    }
  else
    echo FAILURE
    echo FILE $new does not exist
  fi
done
else
    echo WARNING
    echo no file has been checked
fi


cd ../

} | tee report.txt
