#!/usr/bin/env bash
#clear
#export PS4='\e[90m+${LINENO} in ${#BASH_SOURCE[@]}>${FUNCNAME[0]}:${BASH_SOURCE[@]##*/} \e[0m'
#set -x

test.suite.level()
{
  level=$1
  case $1 in
      ''|*[!0-9]*) 
        level=$3
        ;;
      *) echo test.suite level=$level ;;
  esac
  if [ -z "$level" ]; then
    level=$LOG_LEVEL
  fi
  if [ -z "$level" ]; then
    level=3
  fi
}

test.suite.level $*

echo -e "[96m test.suite starting: $0 <LOG_LEVEL=$level>[0m"
# if [ "$level" -gt "5" ]; then
#     set -x
# fi

test.suite.discover() # # discovers all tests
{
  test.suite.run.completion
}

test.suite.run.completion() {
  ls $OOSH_DIR/test/* | sed 's/\/.*\/oosh\/test\/\(interactive.\)*test\.//' | grep "^$1"
}

test.suite.parameter.completion.test() {
  test.suite.run.completion 
}

test.suite.save.results()
{
  source $OOSH_DIR/config 
  config.save testresult TEST_SUITE
  #check file $CONFIG_PATH/testresult.env exists;
  #expect 0 "*" "$CONFIG_PATH/testresult.env exists"
}

test.suite.init()
{
  source this
  source log
  log.init.colors


  if [ -z "$TEST_COUNTER" ]; then
    declare -i TEST_SUITE_TEST_COUNTER=0
    declare -i TEST_SUITE_EXPECT_COUNTER=0
    declare -i TEST_SUITE_SUCCESS_COUNTER=0
    export SUITE_RESULT="Suite Resut: "
  fi

  if (this.isSourced); then
    debug.log "test.suite sourced"
    if [ "$2" = "clear" ]; then
      clear
    fi
    export PS4='\e[90m  ${BASH_SOURCE[0]##*/} -> ${BASH_SOURCE[1]##*/}: ${FUNCNAME[0]}:${LINENO}   - ${BASH_SOURCE[@]##*/} \e[0m'
    if [ "$LOG_LEVEL" -gt "5" ]; then
        set -x
    fi
  else
    #important.log "test.suite started"
    this.start "$@"
  fi
} 

test.suite.run() # <test> <?logLevel:1> # runs a test from the test folder
{
  local command=$1
  shift
  local level=$1
  shift
  local clear=$1
  shift

  if [ -z "$level" ]; then
    level=1
  fi
  if [ "$LOG_LEVEL" -gt "5" ]; then
      set -x
  fi

  if [ "$level" -gt 0 ]; then
    important.log "starting test: $OOSH_DIR/test/test.$command -level:$level- -clear:$clear-"
    $OOSH_DIR/test/test.$command $level $clear
  else
    $OOSH_DIR/test/test.$command $level $clear >/dev/null
  fi

  if check file $CONFIG_PATH/testresult.env exists; then 
    source $CONFIG_PATH/testresult.env
  fi
  console.log "========================================================================================
  test suite done with: $OOSH_DIR/test/test.$command $*"
  console.log "========================================================================================
  \e[1;32m$TEST_SUITE_SUCCESS_COUNTER\e[0m / $TEST_SUITE_EXPECT_COUNTER expects on $TEST_SUITE_TEST_COUNTER Test Cases
  "
  if [ "$TEST_SUITE_SUCCESS_COUNTER" -eq "$TEST_SUITE_EXPECT_COUNTER" ]; then
    success.log "All tests successfull"
    return 0
  else
    error.log "Some tests failed"
    return 1
  fi
}

test.suite.all() # # runs all tests from the test folder
{
  local level=$1
  shift
  local clear=$1
  shift

  for file in $OOSH_DIR/test/test.*
    do
      #if [ "$LOG_LEVEL" -gt 2 ]; then
        stop.log "test.suite about to run: $file $level $clear"  
      #fi
      if [ "$LOG_LEVEL" -gt 0 ]; then
        $file $level $clear
      else
        $file $level $clear >/dev/null
      fi

      if check file $CONFIG_PATH/testresult.env exists; then 
        source $CONFIG_PATH/testresult.env
      fi
      console.log "========================================================================================
      test suite done with: $OOSH_DIR/test/test.$command $*"
      console.log "========================================================================================
      \e[1;32m$TEST_SUITE_SUCCESS_COUNTER\e[0m / $TEST_SUITE_EXPECT_COUNTER expects on $TEST_SUITE_TEST_COUNTER Test Cases
      "
      if [ "$TEST_SUITE_SUCCESS_COUNTER" -eq "$TEST_SUITE_SUCCESS_COUNTER" ]; then
        success.log "All tests successfull"
      else
        error.log "Some tests failed"
        return 1
      fi
    done
}

test.case()  # <logLevel:-> <testName> <testFunction> <testArguments> # runs a test case from the test folder
{
  ((TEST_SUITE_TEST_COUNTER++))

  local level=$1
  shift
  # if ! [ "$level" = "-" ]; then
  #   this.call log.level $level
  # fi
  export testName=$1
  shift
  local testFunction="$1"
  shift
  local testArguments="$@"

  if ! [ "$level" = "-" ]; then
    log.level $level
  fi
  if [ "$LOG_LEVEL" -gt "5" ]; then
      set -x
  fi

console.log "

${BOLD_YELLOW}Test $TEST_COUNTER: $testName
= log level $LOG_LEVEL ($level) ======================================================"
  test.console.log "${BOLD_CYAN}testing: $testFunction $testArguments${NORMAL}"
  if [ "$LOG_LEVEL" -gt "1" ]; then
    $testFunction $testArguments
    RETURN_VALUE=$?
  else
    {
      $testFunction $testArguments
      RETURN_VALUE=$?
    } >/dev/null
  fi
if [ "$RETURN_VALUE" -gt 0 ]; then 
  onError
fi
console.log "${BOLD_YELLOW}RETURN: $RETURN_VALUE  Result: $RESULT 
===================================================================="
    #log.level reset
}

expect() # <returnValue> <expectedResult> <message> # checks after a test.case if the result is as expected
{
  ((TEST_SUITE_EXPECT_COUNTER++))
  info.log "$SUITE_RESULT"
  let EXPECTED_RETURN_VALUE=$1
  shift
  local expectedresult="$1"
  shift
  local message="$1"
  shift

  declare -i rv=$RETURN_VALUE
  #console.log "${BOLD_CYAN}starting on testcase: \#$TEST_COUNTER - $testcase${NORMAL}"

  if [ -z "$message" ]; then
    message=$testName
  fi
  #info.log "Testing $TEST_COUNTER: $testcase"
  #$testcase >/dev/null

  if [ "$expectedresult" = "*" ]; then
    expectedresult=$RESULT
  fi 

  if [ "$EXPECTED_RETURN_VALUE" = "*" ]; then
    EXPECTED_RETURN_VALUE=$RETURN_VALUE
  fi 

  if [ "$EXPECTED_RETURN_VALUE" -eq $rv ] && [ "$RESULT" = "$expectedresult" ]; then
    ((TEST_SUITE_SUCCESS_COUNTER++))
    test.success.log "success on testcase $TEST_COUNTER: $testcase $message${NORMAL}\n"
  else
    error.log "error on testcase $TEST_COUNTER: $testcase $message"
    error.details.log "expected $EXPECTED_RETURN_VALUE but got $RETURN_VALUE"
    error.details.log "expected result: $expectedresult"
    error.details.log "        but got: $RESULT"

  fi
  TEST_SUITE_RESULT="${BOLD_GREEN}$SUCCESS_COUNTER${NORMAL} / $EXPECT_COUNTER expects on $TEST_COUNTER Tests"

}

test.suite.new() # <newClassName> # creates a new script that acts as a oo class with completion
{
  if [ -n "$1" ]; then
    info.log "oosh in $OOSH_DIR"

    cd $OOSH_DIR/test
    if [ -f "test.$1" ]; then
      warn.log "File exists: test.$1"
      return 1
    fi
    cat ./../templates/code/new_script_test | sed 's/new_script/'"$1"'/' > test.$1
    chmod +x ./test.$1
    success.log "created test script test.$1"

  else
    warn.log "usage: oo new filename
    
    please specify a filename"
    return 1
  fi
}

test.suite.usage() # #
{
  local this=${0##*/}
  echo "You started 
$0

  current log level: $LOG_LEVEL
  
  current file: $CONFIG
   CONFIG_PATH=$CONFIG_PATH
   CONFIG_FILE=$CONFIG_FILE


  Usage:
  $this: command   description and Parameter
      all       tests all tests in $OOSH_DIR/test 
                $this all <log level>  <?clear>
      run       runs a single test: $OOSH_DIR/test/test.<command>
                $this <command> <log level>  <?clear>      

  
  Examples
    $this run loop 5
    $this all 1 clear
  "
  
  #loop.list PATH print '---------------------: '
}

test.suite.init "$@"
