#!/bin/bash

set -E

export ErrorTracker=$(mktemp)
echo "0" > $ErrorTracker

NoIndent="_noIdent--##$RANDOM"

format() {
  while IFS='' read -e -r line; do
    if [[ ! "$line" =~ "$NoIndent".* ]]; then
      printf "  $line\n"
    else
      printf "${line/$NoIndent/}\n"
    fi
  done
}

trap 'echo $? > "$ErrorTracker"' ERR

{

Info="\033[1;35m"
File="\033[1;34m"
Pass="\033[1;32m"
Error="\033[1;31m"
Nc="\033[0;00m"

decl_file() {
  printf "${NoIndent}${File}$1\n${Nc}"
}

checktest() {
  if [ -n "$2" ]; then
    wait "$2"
    local exitcode=$?
  else
    local exitcode=$1
  fi
  if [[ $exitcode == "0" ]]; then
    printf "${NoIndent}${Pass}Tests passed!\n${Nc}\n"
  else
    printf "${NoIndent}${Error}Tests failed!\n${Nc}\n"
    exit 1
  fi
}

header() {
  printf "${NoIndent}${Info}$1${Nc}\n"
}

finish() {
  printf "${NoIndent}${Info}OK!${Nc}\n"
}

testdirectory() {
  local directory="$1"
  local command="$2"
  local varname="$3"
  local pattern="$4"
  [[ ! -n $pattern ]] && pattern=".*"

  for file in "$directory"/*; do
    if [[ $file =~ $pattern ]]; then
      decl_file "$file"
      local rq_file="${file//\//\\/}"
      eval "$(sed -E "s/\\\$[{]?${varname}[}]?/\"${rq_file}\"/" < <(echo "${command}"))"
      checktest "$?" "$!" || exit 1
    fi
  done
}

header "Parser tests:"
testdirectory "test/parser" './${file}' 'file'

header "Compilation tests:"
testdirectory "test/test-files" './powscript --no-std -c ${file} >/dev/null' '.*\.pow'

header "String tests:"
testdirectory "test/strings" './powscript --no-std ${file}' 'file' '.*\.pow'

header "Function tests:"
testdirectory "test/functions" './powscript --no-std ${file}' 'file' '.*\.pow'

header "Collections tests:"
testdirectory "test/collections" './powscript --no-std ${file}' 'file' '.*\.pow'

header "Control flow tests:"
testdirectory "test/control-flow" './powscript --no-std ${file}' 'file' '.*\.pow'

header "Math tests:"
testdirectory "test/math" './powscript --no-std ${file}' 'file' '.*\.pow'

header "Evaluation tests:"
testdirectory "test/test-files" './powscript ${file}' 'file' '.*\.pow'

header "Library tests:"
testdirectory "test/lib" './powscript ${file}' 'file' '.*\.pow'

header "Interactive mode tests:"
testdirectory "test/interactive" './powscript --no-std --interactive < ${file}' 'file'

header "Repository maintainance tests:"
testdirectory "test/repo" './${file}' 'file' '.*\.sh'

header "Other:"
testdirectory "test/etc" './${file}' 'file'

finish

} | format

Err="$(cat "$ErrorTracker")"
rm $ErrorTracker

if [[ $Err != 0 ]]; then
  echo "Error code: ${Err}"
fi

exit $Err
