#!/bin/bash
# 
# Testing the installation: the version, paths and number of extensions should be correct
# This test entirely depends on the CamitK version (version string, number of extensions...)
# (see the expectedConfigOutput)
# 
# For a CamiTK major or minor version update the expected number and release date
# 
# echo $? get the last returned value of the script
# a return value of 0 indicates success (by convention)
# The value return by this script corresponds to the config test that failed
# (see log for config test id)
# 

set -e

# Uncomment next line to debug
# set -x

# cleanup on exit
cleanup() {
    # backup the current exit status
    currentExitValue=$?
    if [[ "$osName" != "Windows" ]]; then
        # kill the xfvb
        kill $xvfbPid    
    fi
    # cleanup current dir (but not build dir!)
    if [ "$inBuild" == "0" ] ; then
        rm -rf $workingDir
    fi
    # use the backup value (otherwise the result of the "rm -rf" command above will
    # be used, and that's probably always 0 !)
    exit $currentExitValue
}

# ---------------------- checkcommand ----------------------
checkcommand() {
    # usage: checkcommand name 
    if [ "$inBuild" == "0" ] ; then
        # check if current build is on windows debug version
        if ! hash ${1} 2>/dev/null; then
            echo "Executable not found"
        else
            echo "[OK]"
        fi
    else
        if [ ! -x ${1} ] ; then 
            echo "File not found or not executable"
        else
            echo "[OK]"
        fi
    fi
}

# ---------------------- init ----------------------
init() {
    echo "========== checking camitk configuration =========="
    exitStatus=0 # nothing bad. By convention exit 0 indicates success

    if [ $# -lt 1 -o "$1" != "-inbuild" ] ; then
        echo "===== Testing installed version ====="
        inBuild=0
        workingDir=$(mktemp --tmpdir -d camitk-test-tmp.XXXXXXXXXX)
        cd $workingDir
        echo "===== Temporary directory created $workingDir ====="
        camitkConfig="camitk-config"        
    else
        # if -inbuild option is specified, then the next argument should be the build dir (as set by ${PROJECT_BINARY_DIR} by cmake
        workingDir=$2
        echo "===== Testing in build dir $workingDir ====="
        inBuild=1
        cd $workingDir
        camitkConfig="bin/camitk-config"
    fi

    echo "===== Check OS ====="
    unameOS=$(uname)
    if [[ "$unameOS" =~ ^MINGW64.* || "$unameOS" =~ ^MSYS_NT.* ]]; then
        osName="Windows"
    else
        osName="Linux"
    fi
    echo "===== Uname is $unameOS ===== OS is $osName ====="

    if [[ "$osName" != "Windows" ]]; then
        echo "===== Configuring xvfb ====="
        # Starts the server first (to avoid a distracting warning output due to OpenGL context)
        Xvfb :5 -screen 0 1600x1200x24 -ac +extension GLX +render -noreset -v  -fbdir $workingDir/ &
        xvfbPid=$!
        echo "PID of Xvfb: $xvfbPid"
        export DISPLAY=:5
        export XAUTHORITY=/dev/null
    fi

    # Checking config executable
    echo "===== Checking $camitkConfig ====="
    checkCamiTKConfig=$(checkcommand $camitkConfig)
    echo $checkCamiTKConfig
    if [ "$checkCamiTKConfig" != "[OK]" ] ; then
        if [[ "$osName" == "Windows" ]]; then
            camitkConfig=$camitkConfig-debug
            echo "===== Checking ${camitkConfig} ====="
            checkCamiTKConfig=$(checkcommand $camitkConfig)
            echo $checkCamiTKConfig
        fi
    fi
}

# ---------------------- getconfig ----------------------
getconfig() {
    # initialize config output
    echo "===== Get CamiTK configuration ====="
    $camitkConfig --config > ./config-output 2>&1
    camitkConfig=$(cat config-output | sed "s/QStandardPaths.*'.*'//")

    echo "===== config-output ====="
    cat ./config-output

    echo "===== camitkConfig ====="
    echo $camitkConfig
}

# ---------------------- expected value ----------------------
getExpectedValue() {
  case "$1" in
    "Global Installation Directory")
      # for package test: it should always be /usr
      echo "/usr"
      ;;
    "Current Working Directory")
      # this is an upstream test, it should be ran in build dir (for windows, remplace ^/c by C:
      echo $(pwd) | sed -e "s+^/c+C:+"
      ;;
    "Number of Component Extensions")
      case "$shortVersion" in
        "4.0" | "4.1" | "4.2")
          echo "14" # 11 in sdk, imaging and modeling and 3 in tutorials
          ;;
        "3.3" | *)
          echo "12" 
          ;;
      esac
      ;;       
    "Number of Action Extensions")
      case "$shortVersion" in
        "4.0" | "4.1" | "4.2")
          echo "27" # 19 in sdk, imaging and modeling and 8 in tutorials
          ;;
        "3.3" | *)
          echo "71"
          ;;
      esac
      ;;
    "Number of File Extensions Supported")
      case "$shortVersion" in
        "4.0" | "4.1" | "4.2")
          echo "37" # 34 in sdk, imaging and modeling and 3 in tutorials
          ;;
        "3.3" | *)
          echo "35"
          ;;
      esac
      ;;
    "Number of Actions")
      case "$shortVersion" in
        "4.0" | "4.1" | "4.2")
          echo "105" # 92 in sdk, imaging and modeling and 14 in tutorials
          ;;
        "3.3" | *)
          echo "81"
          ;;
      esac
      ;;
  esac
}

# ---------------------- getInstalledVersion ----------------------
getInstalledVersion() {
  echo $(echo $camitkConfig | head --lines=1 | cut -f5 -d" ")
}

# ------------------- getReleaseDate -------------------
getReleaseDate() {
  # get the release date of minor version 
  if [[ $1 =~ .*dev.* ]]; then
    echo "not yet released"
  else
    case "$1" in
        "3.0")
           echo "7 July 2012"
           ;;
        "3.1")
           echo "1 March 2013"
           ;;
        "3.2")
           echo "26 June 2013"
           ;;
        "3.3")
           echo "4 March 2014"
           ;;
        "3.4")
           echo "31 October 2014"
           ;;
        "3.5")
           echo "29 January 2016"
           ;;
        "4.0")
           echo "22 July 2016"
           ;;
        "4.1")
           echo "15 July 2018"
           ;;
        *)
           echo "unknown version"
           ;;
      esac
  fi
}

# ---------------------- extension count ----------------------
getExtensionCount() {
  echo $(echo "$camitkConfig" | grep "^  - \[$1\] " | wc -l)
}

getExpectedExtensionCount() {
  case "$1" in
    "4.0" | "4.1" | "4.2")    
      echo "41"  # 30 extensions in sdk, imaging and modeling and 11 extensions in tutorials
      ;;
    "3.3" | *)
      echo "12" 
      ;;    
  esac
}

# ---------------------- get config ----------------------
# get a specific value from config, text to parse from
# camitk-config --config is the first parameter of the function
# get the value after the string "... " and before the first space
getConfigValue() {
  echo $(echo "$camitkConfig" | grep "$1" | sed 's/^.*\.\.\. //g' | cut -f1 -d" ")
}

# ---------------------- check value ----------------------
# use camitk-config to check a value and compare to 
# expected value
checkValue() {
  checkedValue="$1"
  value=$(getConfigValue "$checkedValue")
  echo "===== $checkValueId- $checkedValue: $value ====="
  expected=$(getExpectedValue "$checkedValue")
  if [ "$value" != "$expected" ]; then
    echo "Error: unexpected $checkedValue (found $value vs $expected expected)"
    exitStatus=$checkValueId
  else
    echo "OK"
  fi
  # increase id
  checkValueId=$((checkValueId+1))
}

# --------------------------------------------------------------------------
#
# All tests are here
#
# --------------------------------------------------------------------------

# if a problem occurs, call the clean method
trap "cleanup" 0 INT QUIT ABRT PIPE TERM EXIT

init $*
getconfig

detectedVersion=$(getInstalledVersion)
shortVersion=$(echo $detectedVersion | cut -f1,2 -d".")
echo "===== 1- Detected installed CamiTK version is: [$detectedVersion] aka [$shortVersion] ====="
releaseDate=$(getReleaseDate $shortVersion)
if [ "$releaseDate" = "unknown version" ]; then
  echo -n "Error: unknown version "
  exitStatus=1
else
  echo -n "OK "
fi
echo "(release date: $releaseDate)"

if [ "$inBuild" == "0" ] ; then
  extensionRepository="G" # check for globally installed extension
else
  extensionRepository="W" # check extension in current build dir
fi

value=$(getExtensionCount $extensionRepository)
echo "===== 2- Number of extensions: $value ====="
expected=$(getExpectedExtensionCount $shortVersion)
if [ "$value" -ne "$expected" ]; then
  echo "Error: unexpected number of globally installed extensions (found $value vs $expected expected)"
  exitStatus=1
else
  echo "OK"
fi

# init the id (next test is the third test)
checkValueId=3
if [ "$inBuild" == "0" ] ; then
  checkValue "Global Installation Directory"
else
  checkValue "Current Working Directory"
fi
checkValue "Number of Component Extensions"
checkValue "Number of Action Extensions"
checkValue "Number of File Extensions Supported"
checkValue "Number of Actions"

exit $exitStatus
