#!
#! @ingroup group_sdk_cmake_camitk_test
#!
#! This CMake script run the action state machine and compare the output files to the expected files
#! The intended use is to run this script from the camitk_add_test_actionstatemachine 
#!
#-- declare outputfiles
set(CAMITK_TEST_COMMAND_FILE ${CAMITK_TEST_OUTPUT_DIR}/command) # which command is run to test the exectable
set(CAMITK_TEST_COMMAND_RESULT_FILE ${CAMITK_TEST_OUTPUT_DIR}/command-result) # the exit result (0=success, 1=failure) of the tested command goes in this file
set(CAMITK_TEST_COMMAND_OUTPUT_FILE ${CAMITK_TEST_OUTPUT_DIR}/command-output) # the output of the tested command goes in this files
set(CAMITK_TEST_EXPECTED_FILE_COMMAND_FILE ${CAMITK_TEST_OUTPUT_DIR}/test) # which command is run to diff the files
set(CAMITK_TEST_EXPECTED_FILE_OUTPUT_FILE ${CAMITK_TEST_OUTPUT_DIR}/test-output) # output of the diff cmake command
set(CAMITK_TEST_EXPECTED_FILE_RESULT_FILE ${CAMITK_TEST_OUTPUT_DIR}/test-result) # exit result (0=success, 1=failure)

# clean/remove all output files and previous test attempt
unset(PREVIOUS_ATTEMPTS)
file(GLOB ALL_OUTPUT_FILES ${CAMITK_TEST_OUTPUT_DIR}/*)
foreach(POTENTIAL_DIR ${ALL_OUTPUT_FILES})
    # only remove subdirectories (as they are previous attempts of running the test and should be asm output directory)
    if(IS_DIRECTORY ${POTENTIAL_DIR})
        list(APPEND PREVIOUS_ATTEMPTS ${POTENTIAL_DIR})
    endif()
endforeach()
file(REMOVE_RECURSE ${CAMITK_TEST_COMMAND_FILE} ${CAMITK_TEST_COMMAND_RESULT_FILE} ${CAMITK_TEST_COMMAND_OUTPUT_FILE} ${CAMITK_TEST_EXPECTED_FILE_COMMAND_FILE} ${CAMITK_TEST_EXPECTED_FILE_OUTPUT_FILE} ${CAMITK_TEST_EXPECTED_FILE_RESULT_FILE} ${PREVIOUS_ATTEMPTS})

#--  First run the executable
# Build the command file (so the user can retrieve/review it later)
file(WRITE ${CAMITK_TEST_COMMAND_FILE} "${CAMITK_TEST_COMMAND} ${CAMITK_TEST_COMMAND_ARG}")

# expands all arguments
string(REPLACE " " ";" CAMITK_TEST_COMMAND_ARG_LIST ${CAMITK_TEST_COMMAND_ARG})

# execute the command and write the output to the command-output file, and the result to the command-result file
execute_process(
  COMMAND ${CAMITK_TEST_COMMAND} ${CAMITK_TEST_COMMAND_ARG_LIST}
  RESULT_VARIABLE CAMITK_TEST_COMMAND_RESULT
  OUTPUT_VARIABLE CAMITK_TEST_COMMAND_OUTPUT
  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
file(WRITE ${CAMITK_TEST_COMMAND_RESULT_FILE} ${CAMITK_TEST_COMMAND_RESULT})
file(WRITE ${CAMITK_TEST_COMMAND_OUTPUT_FILE} ${CAMITK_TEST_COMMAND_OUTPUT})

# Transform back the "::" separated list of expected output to a classic ";" separated string
string(REPLACE "::" ";" CAMITK_TEST_EXPECTED_FILES_LIST ${CAMITK_TEST_EXPECTED_FILES})

set(CAMITK_TEST_EXPECTED_FILE_OUTPUT "Action state machine regression test called with:\n - CAMITK_TEST_NAME=${CAMITK_TEST_NAME}\n - CAMITK_TEST_COMMAND=${CMAKE_BINARY_DIR}/bin/camitk-actionstatemachine\n - CAMITK_TEST_COMMAND_ARG=${CAMITK_TEST_COMMAND_ARG}\n - CAMITK_TEST_EXPECTED_FILES=${CAMITK_TEST_EXPECTED_FILES_LIST}\n - CAMITK_TEST_OUTPUT_DIR=${CAMITK_TEST_OUTPUT_DIR}\n")
set(CAMITK_TEST_EXPECTED_FILE_RESULT 0)
set(CAMITK_TEST_EXPECTED_FILE_COMMAND)
set(CAMITK_TEST_FAILED_FILE)

#-- Then compare each expected output
foreach(EXPECTED_OUTPUT_FILE ${CAMITK_TEST_EXPECTED_FILES_LIST})
    # find the same file in the asm output directory (*T*)
    file(GLOB_RECURSE OUTPUT_FILE "${CAMITK_TEST_OUTPUT_DIR}/*T*/${EXPECTED_OUTPUT_FILE}")
    
    # compare the files
    execute_process(
        COMMAND ${CMAKE_COMMAND} -E compare_files ${OUTPUT_FILE} ${CAMITK_TEST_OUTPUT_DIR}/${EXPECTED_OUTPUT_FILE}
        RESULT_VARIABLE CAMITK_TEST_EXPECTED_FILE_RESULT_SINGLE
        OUTPUT_VARIABLE CAMITK_TEST_EXPECTED_FILE_OUTPUT_SINGLE
        OUTPUT_QUIET
        ERROR_QUIET
    )
    
    # update the output variables (command, output and result)
    set(CAMITK_TEST_EXPECTED_FILE_OUTPUT
        "${CAMITK_TEST_EXPECTED_FILE_OUTPUT}=================================================\nComparing ${OUTPUT_FILE} with ${CAMITK_TEST_OUTPUT_DIR}/${EXPECTED_OUTPUT_FILE}\nOutput:\n${CAMITK_TEST_EXPECTED_FILE_OUTPUT_SINGLE}\n")
    set(CAMITK_TEST_EXPECTED_FILE_COMMAND 
        "${CAMITK_TEST_EXPECTED_FILE_COMMAND}${CMAKE_COMMAND} -E compare_files ${OUTPUT_FILE} ${CAMITK_TEST_OUTPUT_DIR}/${EXPECTED_OUTPUT_FILE}\n")
    if(CAMITK_TEST_EXPECTED_FILE_RESULT_SINGLE)
        set(CAMITK_TEST_EXPECTED_FILE_OUTPUT "${CAMITK_TEST_EXPECTED_FILE_OUTPUT}Result:\n${CAMITK_TEST_NAME}: comparing ${EXPECTED_OUTPUT_FILE} failed:\nOutput file ${CAMITK_TEST_OUTPUT_DIR}/${EXPECTED_OUTPUT_FILE} is not the same as ${OUTPUT_FILE}\n\n" )
        set(CAMITK_TEST_EXPECTED_FILE_RESULT 1)
        set(CAMITK_TEST_FAILED_FILE "${CAMITK_TEST_FAILED_FILE}${EXPECTED_OUTPUT_FILE}\n")
    else()
        set(CAMITK_TEST_EXPECTED_FILE_OUTPUT "${CAMITK_TEST_EXPECTED_FILE_OUTPUT}Result:\n${CAMITK_TEST_NAME}: comparing ${EXPECTED_OUTPUT_FILE} success!\n\n" )    
    endif()
endforeach()

#-- write everything to the test-command, test-output and test-result files 
#   These information detail the results for an easier diagnostic by a human
file(WRITE ${CAMITK_TEST_EXPECTED_FILE_COMMAND_FILE} ${CAMITK_TEST_EXPECTED_FILE_COMMAND})
file(WRITE ${CAMITK_TEST_EXPECTED_FILE_OUTPUT_FILE} ${CAMITK_TEST_EXPECTED_FILE_OUTPUT})
file(WRITE ${CAMITK_TEST_EXPECTED_FILE_RESULT_FILE} ${CAMITK_TEST_EXPECTED_FILE_RESULT})

#-- check result
if( CAMITK_TEST_EXPECTED_FILE_RESULT )
    message(STATUS "[FAIL]")
    message(FATAL_ERROR "${CAMITK_TEST_NAME}: (one or more) output file do(es) not match the corresponding expected file.\n${CAMITK_TEST_EXPECTED_FILE_OUTPUT}" )
else()
    message(STATUS "[OK]")
endif()
