#!/bin/bash
# Testing the installation of the dev tools
# cepgenerator and devtools
# 
# echo $? get the last returned value of the script
#
# TODO add complete library tests using cepgenerator
# This can be done using exampleLibraryAction.xml 
# + adding a real action in there 
# + adding a component
# + adding a test file
# + adding source code files :
#   ActionDoSomething.cpp in 
#   EmptyComponent.cpp to use the library
#   EmptyLibrary.h EmptyLibrary.cpp
# + add "echo "#include "ActionDoSomething.cpp"" >> actions/emptyaction/Action.cpp"
# and compile only then
# @see the shaker lib turorial
#
# TODO add a complete example with all the possible Property types
# @see the property tutorial
#
# TODO add another family of tests using testaction and testcomponent on cepgenerated action/components
#
# TODO distribute all the files from the ./sdk/applications/cepgenerator/testdata directory 
# in the package $(pkg-dev) so that they are installed in /usr/share/camitk-$(VER_SHORT)/testdata/cepgenerator/*
# In this script, just copy all files from /usr/share/camitk-$(VER_SHORT)/testdata/cepgenerator/* to the tmpdir
# and run a foreach on each .xml files

set -e

# Uncomment next line to debug
# set -x

#DEBUG
#To test with different library versions, you can use different install path, for instance:
# CMAKE_OPTIONS="-DVTK_DIR:PATH=/opt/vtk6/lib/cmake/vtk-6.3 -DITK_DIR:PATH=/opt/vtk6/lib/cmake/ITK-4.9 -DGDCM_DIR:PATH=/opt/vtk6/lib/gdcm-2.6"

# ---------------------- cleanup ----------------------
cleanup() {
    # cleanup on exit
    
    # backup the current exit status
    currentExitValue=$?
    if [[ "$osName" != "Windows" ]]; then
        # kill the xfvb
        kill $xvfbPid    
    fi
    if [ "$currentExitValue" -ne "0" ]; then
        # output all possible files
        cd $workingDir
        echo
        echo "===== ABORTED ====="
        echo
        # Test exist status of every file and directory otherwise the script abort and the temp directory is not removed
        if [ -f "./generated-$testDirName" ]; then
            echo "===== ABORTED generated-$testDirName ====="
            cat ./generated-$testDirName
        else 
            echo "===== File $workingDir/generated-$testDirName not found ====="
        fi
        if [ -d "$testDirName/build" ]; then
            cd $testDirName/build
            if [ -f "../cmake-log" ]; then
                echo "===== ABORTED cmake-log ====="
                cat ../cmake-log
            else
                echo "===== File $testDirName/build/../cmake-log not found ====="
            fi
            if [ -f "../cmake-error" ]; then
                echo "===== ABORTED cmake-error ====="  
                cat ../cmake-error
            else
                echo "===== File $testDirName/build/../cmake-error not found ====="
            fi
            if [ -f "../make-log" ]; then
            echo "===== ABORTED make-log ====="
            cat ../make-log
            else
                echo "===== File $testDirName/build/../make-log not found ====="
            fi
            if [ -f "../make-error" ]; then
            echo "===== ABORTED make-error ====="  
            cat ../make-error
            else
                echo "===== File $testDirName/build/../make-error not found ====="
            fi
        else
            echo "===== Directory $workingDir/$testDirName/build not found ====="            
        fi
        cd
    fi
    # finally cleanup working dir
    rm -rf $workingDir
    # 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-dev installation... ====="
    exitStatus=0 # nothing bad. By convention exit 0 indicates success
    checkValueId=1 # test id starts at 1
    scriptDir=$(dirname "$0")
    echo "===== Script directory is $scriptDir ====="

    echo "===== Creating temporary directory ====="
    workingDir=$(mktemp --tmpdir -d camitk-test-tmp.XXXXXXXXXX)
    echo "===== Temporary directory set to $workingDir ====="
    
    echo "===== Run with $# parameters. $1 $2 ====="
    if [ $# -lt 1 -o "$1" != "-inbuild" ] ; then
        echo "===== Testing installed camitk version ====="
        inBuild=0
        # for installed camitk, just run the corresponding executables
        camitkGenerator=camitk-cepgenerator
        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
        echo "===== Testing in build dir $2 (sources in $3) ====="
        inBuild=1
        # for in build test, use specific path for executables
        camitkGenerator=$2/bin/camitk-cepgenerator
        camitkConfig=$2/bin/camitk-config
        # specify CamiTK dir 
        # Although it is not an install dir, it is better to use the build dir than to temporary installed, test and uninstall
        export CAMITK_DIR=$2
        # Add extra cmake module path to find the CMake macros that are indeed not installed in the build dir
        CMAKE_OPTIONS="$CMAKE_OPTIONS -DCMAKE_MODULE_PATH:PATH=$3/sdk/cmake/modules;$3/sdk/cmake/modules/macros"
    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 if current build is on windows debug version
    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
    echo "===== Using $camitkConfig on $osName ====="
    echo "===== Checking $camitkGenerator ====="
    checkCamiTKGenerator=$(checkcommand $camitkGenerator)
    echo $checkCamiTKGenerator
    if [ "$checkCamiTKGenerator" != "[OK]" ] ; then
        if [[ "$osName" == "Windows" ]]; then
            camitkGenerator=$camitkGenerator-debug
            echo "===== Checking $camitkGenerator ====="
            checkCamiTKGenerator=$(checkcommand $camitkGenerator)
            echo $checkCamiTKGenerator
        fi    
    fi
    echo "===== Using $camitkGenerator on $osName ====="
    
}

# ---------------------- generateSourceFiles ----------------------
generateSourceFiles() {
  echo "===== generate coreschema and C++ source files ====="
  $scriptDir/generate-coreschema-files.sh
  $scriptDir/generate-cpp-files.sh
}

# ---------------------- getConfig ----------------------
getConfig() {
  $camitkConfig --config 2>/dev/null # | sed "s/QStandardPaths.*'.*'//"
}

# ---------------------- generateConfigureAndMake ----------------------
getWorkingDirExtensionCount() {
  echo $(getConfig | grep "^  - \[W\] " | wc -l)
}

# ---------------------- generateConfigureAndMake ----------------------
generateConfigureAndMake() {
  # generate
  testDirName=$(basename $1 .xml)
  echo "================================================================================"
  echo "========== generate, configure and build $testDirName... =========="
  echo "================================================================================"
  echo
  echo "========== generating... =========="
  cd $workingDir
  rm -rf $testDirName
  mkdir $testDirName
  $camitkGenerator -f $1 -d $workingDir/$testDirName > ./generated-$testDirName
  if [ -s ./generated-$testDirName ] ; then
    echo "===== cepgenerator log ====="
    cat ./generated-$testDirName
  fi

  cd $testDirName
  # get the created dir name
  srcDirName=$(ls)
 
  # check if there is a library (in this case copy dummy test lib to the given library name source dir
  if [ "$#" == 2 ]; then
    echo "===== Adding library code... ====="
    cp ../TestLib.* $srcDirName/libraries/$2
  fi

  # configure
  mkdir build
  cd build
  echo "===== configuring... ====="
  if [[ "$osName" == "Windows" ]]; then
    # no virtual X11 -DCMAKE_C_FLAGS:STRING="/MP" -DCMAKE_CXX_FLAGS="/MP" 
    cmake $CMAKE_OPTIONS -Wno-dev -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE:STRING=Debug ../$srcDirName > ../cmake-log 2> ../cmake-error
  else
    cmake $CMAKE_OPTIONS ../$srcDirName > ../cmake-log 2> ../cmake-error
  fi
  if [ -s ../cmake-log ] ; then
    echo "===== cmake log ====="
    cat ../cmake-log
  fi
  if [ -s ../cmake-error ] ; then
    echo "===== cmake error log ====="  
    cat ../cmake-error
  fi

  echo "===== building... ====="
  if [[ "$osName" == "Windows" ]]; then
    cmake --build . --config Debug > ../make-log 2> ../make-error
  else
    # build (parallel)
    make -j9 > ../make-log 2> ../make-error
  fi
  if [ -s ../make-log ] ; then
    echo "===== make log ====="
    cat ../make-log
  fi
  if [ -s ../make-error ] ; then
    echo "===== make error log ====="  
    cat ../make-error
  fi
}

# ---------------------- testcepfile ----------------------
# @param xmlfile
# @param expected number of created extensions
testcepfile() {
  generateConfigureAndMake $1 $3
  expectedValue="$2"

  echo "========== check $1 =========="
  
  # check if everything is compiled and can be loaded
  value=$(getWorkingDirExtensionCount)
  echo "$checkValueId- Check Number of extensions for $1: $value"
  echo "$(getConfig | grep "^  - \[W\] ")"
  if [ "$value" -ne "$expectedValue" ]; then
    echo "Error: unexpected number of extensions installed in the working directory ($value != $expectedValue)"
    exitStatus=$checkValueId
  else
    echo "OK"
  fi
  echo
  # 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 $*
cd $workingDir
generateSourceFiles

#testcepfile cep.xml nrOfExpectedNewExtensions
if [[ "$osName" == "Windows" ]]; then
    echo "Windows: skip testing cep with lib"
else
    testcepfile completeTest1.xml 3 testlib
fi
testcepfile exampleComponents.xml 2
testcepfile actionsExamplesLicence.xml 2
testcepfile actionsExamplesNoLicence.xml 2
testcepfile actionAndComponent.xml 2
testcepfile empty.xml 0 

exit $exitStatus
