#!/bin/bash

# Run complete test suite
# Usage: ./test-suite.sh
# Expected base dir (when launching): same of source repository  (e.g. "workspace/qcs-2.0/src/bin)
echo
echo ">>> Running QCS test-suite"
echo

# Select execution environment (used only when running from distro directory)
echo "HINT: If running from workspace -> ignore next two 'bad substitution' messagges"
QCS_NAME=jrc-qcs
QCS_VERSION=2.3.9
echo

# Understand if Maven assembly has already filtered the QCS_VERSION variable
QCS_VER_LENGTH=${#QCS_VERSION}
echo "Length of qcs_version variable: $QCS_VER_LENGTH"
if [ $QCS_VER_LENGTH = 0 ]
then
    FROM_WORKSPACE=true
else
    FROM_WORKSPACE=false
fi

###################################################################
###				 		BEGIN LOCAL PROFILE 					###
###################################################################

# 1. SET HERE THE ABSOLUTE PATH OF THE TEST FILES
# DATA_HOME="Write here your local absolute path to the test-suite's data"
# EXAMPLES:
# Windows Lenovo path (Stefano@WELCOME)
# DATA_HOME="C:/Users/adriste/Home/workspace/qcs-2.0/src/test/resources/test-data"
# Windows Vantage path (Stefano@HOME)
# DATA_HOME="C:/Home/Workspace/qcs-2.0/src/test/resources/test-data"

# 2. SET HERE THE NAME OF THE IDE PROJECT
# PROJECT_NAME="Write here your local absolute path to the project's root"
# EXAMPLES:
# PROJECT_NAME="quality-check-software"
# PROJECT_NAME="qcs-2.2"
# PROJECT_NAME="qcs-2.0"

###################################################################
###				 		END LOCAL PROFILE 						###
###################################################################

if [ -z "$DATA_HOME" ]; then
	echo
    echo "ERROR: The variable DATA_HOME is not set."
    echo "Please set with the absolute path of the test files."
	echo
    echo "Example: C:/Home/Workspace/qcs-2.0/src/test/resources/test-data"
	exit
else
    echo "The variable DATA_HOME is set to: $DATA_HOME"
fi

if [ -z "$PROJECT_NAME" ]; then
	echo
    echo "ERROR: The variable PROJECT_NAME is not set."
    echo "Please set with the absolute path of the sources."
	echo
    echo "Example: C:/Home/Workspace/qcs-2.0"
	exit
else
    echo "The variable PROJECT_NAME is set to: $PROJECT_NAME"
fi

# Prepare execution environment
if [ $FROM_WORKSPACE = true ]
then
	# Moving into workspace directory
	cd ../../..
	echo "From workspace -> moved into directory: $PWD"
	# Set main variables
	QCS_HOME="./"$PROJECT_NAME
else 
	# Moving into releases directory
	cd ..
	echo "From distro -> moved into directory: $PWD"
	QCS_HOME="./"$QCS_NAME-$QCS_VERSION
fi

# Directory where to store all temporary output reports
TEST_HOME=$QCS_HOME"/"test

# If true, all test files will be validated. 
# If false, expected outputs are compared against the previous validation runs.
# REMARK: "false" can be used only if report files are already in the "test/reports" folder.
VALIDATE=true
# If true target output reports are compared against the expected output
TXT_REPORT=true
CSV_REPORT=true
# Maximum number of allowed "formal" differences (negligible)
MAX_DIFF=10

# Log variables
TEST_START=$(date +%s)
OUTPUT_FILE=$QCS_HOME"/"test-outcome.txt
echo -e "**********************************************" | tee -a $OUTPUT_FILE
echo -e " Running QCS Test Suite: $(date)" | tee -a $OUTPUT_FILE
echo -e "**********************************************" | tee -a $OUTPUT_FILE
echo | tee -a $OUTPUT_FILE
echo "QCS_HOME  = $QCS_HOME" | tee -a $OUTPUT_FILE
echo "DATA_HOME = $DATA_HOME" | tee -a $OUTPUT_FILE
echo "TEST_HOME = $TEST_HOME" | tee -a $OUTPUT_FILE

###################################################################
###				 		SELECT TARGET PROTOCOLS 				###
###################################################################

# declare -a protocols=("incidence_2022")
# declare -a protocols=("incidence_2022_pm_strict")
# declare -a protocols=("incidence_2022" "incidence_2022_range" "population_2022" "population_2022_range" "lifetable_2022")
declare -a protocols=("incidence_2022" "population_2022" "population_2022_range" "mortality_2022" "mortality_2022_range" "lifetable_2022")

###################################################################
###				 		SELECT TARGET FILES 					###
###################################################################

# Uncomment this line (and comment the line after it) to run minimal Incidence test
# declare -a inc_files_2022=("incidence_4")
declare -a inc_files_2022=("incidence_1" "incidence_2" "incidence_3" "incidence_4" "incidence_5")
declare -a mor_files_2022=("mortality_1" "mortality_2")
declare -a mor_files_2022_range=("mortality_1" "mortality_2")
declare -a pop_files_2022=("population_1" "population_2")
declare -a pop_files_2022_range=("population_1" "population_2")
declare -a lif_files_2022=("lifetable_1" "lifetable_2")

# Input variables
declare -a protocol_ID
declare -a data_directory
declare -a report_directory
declare -a data_files
declare -a output_report
declare -a input_directory

# Output variables
declare -a expected_report
declare -a produced_report

# Human-readable protocol full name (for logs)
protocol_full_name=""

# HELPER FUNCTION: set the ID of the target protocol
function getProtocolID() {
	case "$1" in
		"incidence_2022")  				protocol_ID="11";;
		"incidence_2022_pm_strict") 	protocol_ID="11";;
		"mortality_2022")  				protocol_ID="13";;
		"mortality_2022_range")  		protocol_ID="14";;
		"population_2022") 				protocol_ID="15";;
		"population_2022_range") 		protocol_ID="16";;
		"lifetable_2022") 				protocol_ID="17";;
	esac
}

# HELPER FUNCTION: set the human-readable protocol full name (for logs)
function getProtocolFullName() {
	case "$protocol_ID" in
		"11") protocol_full_name='Incidence protocol (39 var)';;
		"13") protocol_full_name='Mortality protocol "Age Unit" (7 var)';;
		"14") protocol_full_name='Mortality protocol "Age Range" (7 var)';;
		"15") protocol_full_name='Population protocol "Age Unit" (6 var)';;
		"16") protocol_full_name='Population protocol "Age Range" (6 var)';;
		"17") protocol_full_name='Life Table protocol (6 var)';;
	esac
}

# HELPER FUNCTION: set the value of the directory hosting the INPUT test files
function getInputDirectory() {
	case "$1" in
		"incidence_2022")  				data_directory="2022/incidence";;
		"incidence_2022_pm_strict") 	data_directory="2022/incidence";;
		"mortality_2022")  				data_directory="2022/mortality";;
		"mortality_2022_range")  		data_directory="2022/mortality_range";;
		"population_2022") 				data_directory="2022/population";;
		"population_2022_range") 		data_directory="2022/population_range";;
		"lifetable_2022") 				data_directory="2022/lifetable";;
	esac
}

# HELPER FUNCTION: set the current "data_files" source array
function getFilesArray() {
	case "$1" in
		"incidence_2022")  				data_files=("${inc_files_2022[@]}");;
		"incidence_2022_pm_strict")		data_files=("${inc_files_2022[@]}");;
		"mortality_2022")  				data_files=("${mor_files_2022[@]}");;
		"mortality_2022_range")  		data_files=("${mor_files_2022_range[@]}");;
		"population_2022") 				data_files=("${pop_files_2022[@]}");;
		"population_2022_range") 		data_files=("${pop_files_2022_range[@]}");;
		"lifetable_2022") 				data_files=("${lif_files_2022[@]}");;
	esac
}

# HELPER FUNCTION: set the current TXT output report source array,
# i.e. the lastest file to be copied in the "test/reports" directory.
function getTXTOutputReport() {
	case "$1" in
		"incidence_2022")  				output_report_txt=("incidence/QCS-Incidence-Output.txt");;
		"incidence_2022_pm_strict")		output_report_txt=("incidence/QCS-Incidence-Output.txt");;
		"mortality_2022")  				output_report_txt=("mortality/QCS-Mortality-Output.txt");;
		"mortality_2022_range")  		output_report_txt=("mortality/QCS-Mortality-Output.txt");;
		"population_2022") 				output_report_txt=("population/QCS-Population-Output.txt");;
		"population_2022_range") 		output_report_txt=("population/QCS-Population-Output.txt");;
	esac
}

# HELPER FUNCTION: set the current CSV output report source array,
# i.e. the lastest file to be copied in the "test/reports" directory.
function getCSVOutputReport() {
	case "$1" in
		"incidence_2022")  				output_report_csv=("incidence/QCS-Incidence-Output.csv");;
		"incidence_2022_pm_strict")		output_report_csv=("incidence/QCS-Incidence-Output.csv");;
		"mortality_2022")  				output_report_csv=("mortality/QCS-Mortality-Output.csv");;
		"mortality_2022_range")  		output_report_csv=("mortality/QCS-Mortality-Output.csv");;
		"population_2022") 				output_report_csv=("population/QCS-Population-Output.csv");;
		"population_2022_range") 		output_report_csv=("population/QCS-Population-Output.csv");;
		"lifetable_2022") 				output_report_csv=("lifetable/QCS-LifeTable-Output.csv");;
	esac
}

# HELPER FUNCTION: set the value of the directory hosting the expected OUTPUT reports
function getOutputDirectory() {
	case "$1" in
		"incidence_2022")  				report_directory="2022/incidence";;
		"incidence_2022_pm_strict")  	report_directory="2022/incidence_pm_strict";;
		"mortality_2022")  				report_directory="2022/mortality";;
		"mortality_2022_range")  		report_directory="2022/mortality_range";;
		"population_2022") 				report_directory="2022/population";;
		"population_2022_range")		report_directory="2022/population_range";;
		"lifetable_2022") 				report_directory="2022/lifetable";;
	esac
}

# Creates necessary "QCS/test/reports/" sub-directories
mkdir -p $TEST_HOME
if [ $TXT_REPORT = true ] || [ $CSV_REPORT = true ]
then
	for protocol in "${protocols[@]}"
		do	
			getInputDirectory $protocol
			mkdir -p $TEST_HOME"/"reports/$data_directory
			# echo "protocol: $protocol -> $TEST_HOME"/"reports/$data_directory"
		done
fi

# VALIDATE TEST FILES (cycles through all supported protocols)
if [ $VALIDATE = true ]
then
	index=0
	for protocol in "${protocols[@]}"
	do	
		# Set values of the protocol_ID, data_directory and data_files variables
		getProtocolID $protocol
		getProtocolFullName
		getInputDirectory $protocol
		getFilesArray $protocol
		getTXTOutputReport $protocol
		getCSVOutputReport $protocol
		
		# Log protocol's information
		echo -e "\nTesting ENCR protocol \"$protocol_full_name\" [ID:$protocol_ID]\n" | tee -a $OUTPUT_FILE
		# Cycle through all data files for current protocol
		input_directory=$DATA_HOME"/input/encr/"$data_directory
		echo -e "\tInput directory: $input_directory\n" | tee -a $OUTPUT_FILE
		cd $QCS_HOME
		# Select execution environment
		if [ $FROM_WORKSPACE = true ]
		then
			echo -e "\tMaven execution"
			mvn exec:java -Dexec.args="-d $protocol_ID $input_directory test/reports/$data_directory 0 test"
		else 
			echo -e "\tRunning distro"
			javaw -jar -Xmx2g $QCS_NAME-$QCS_VERSION.jar -d $protocol_ID $input_directory test/reports/$data_directory 0 test
		fi
		cd ..
		index=$index+1
	done
else
	echo -e "\nSkipping validating (using previous results)" | tee -a $OUTPUT_FILE
fi

# Separation line
# echo | tee -a $OUTPUT_FILE

# Init error counters
total=0
reportCounter=0

# COMPARE RESULTS
echo -e "\nCurrent working directory           : $PWD" | tee -a $OUTPUT_FILE
echo -e "Expected reports base directory     : $DATA_HOME/output/encr" | tee -a $OUTPUT_FILE

for protocol in "${protocols[@]}"
do	
	# Set values of the protocol_ID, data_directory and data_files variables
	getProtocolID $protocol
	getProtocolFullName
	getInputDirectory $protocol
	getFilesArray $protocol
	getOutputDirectory $protocol
	# Log protocol's information
	echo -e "\nComparing outputs for ENCR protocol \"$protocol_full_name\" [ID:$protocol_ID]" | tee -a $OUTPUT_FILE		
	echo -e "Tolerance value for comparison: $MAX_DIFF\n" | tee -a $OUTPUT_FILE		
	# Cycle through all test files regarding current protocol
	for file in "${data_files[@]}"
	do
		# Comparing TXT REPORTS
		if [ $TXT_REPORT = true ]
		then
			produced_report=$QCS_HOME"/"test/reports/$data_directory"/"$file".txt"
			expected_report=$DATA_HOME"/output/encr/"$report_directory"/"$file".txt"
			# echo -e "\tComparing: $expected_report VS $produced_report" | tee -a $OUTPUT_FILE
			diff -w $expected_report $produced_report > diff.txt
			reportCounter=$(cat diff.txt | grep -v start | grep -v end | grep -v Validate | wc -l)
			# Tries to count actual differences (after the grep we have some false positive)
			if (($reportCounter <= $MAX_DIFF)) 
			then
				reportCounter=0
			else 
				reportCounter=$(($reportCounter-$MAX_DIFF))
			fi	
			echo -e "\t$report_directory/$file \t--> differences in TXT report: \t$reportCounter" | tee -a $OUTPUT_FILE
		fi
		# Update counter (with TXT differences)
		total=$(($total+$reportCounter))
		# Comparing CSV REPORTS
		if [ $CSV_REPORT = true ]
		then
			produced_report=$QCS_HOME"/"test/reports/$data_directory"/"$file".csv"
			expected_report=$DATA_HOME"/output/encr/"$report_directory"/"$file".csv"
			# echo -e "\tComparing: $expected_report VS $produced_report" | tee -a $OUTPUT_FILE
			diff -w $expected_report $produced_report > diff.txt
			reportCounter=$(cat diff.txt | wc -l)
			# Tries to count actual differences (a single different in a CSV report generates 2 diff results)
			reportCounter=$(($reportCounter/2))
			echo -e "\t$report_directory/$file \t--> differences in CSV report: \t$reportCounter" | tee -a $OUTPUT_FILE
		fi
		# Update counter (with CSV differences)
		total=$(($total+$reportCounter))
	done
done

# Show test outcome
echo -e "\nTest result:\n" | tee -a $OUTPUT_FILE
echo -e "Total errors: $total\n" | tee -a $OUTPUT_FILE
if (($total == 0)) 
then
	echo -e "TEST SUCCESFULL\n" | tee -a $OUTPUT_FILE
 else 
	echo -e "TEST FAILED\n" | tee -a $OUTPUT_FILE
fi

# Logs total time
TEST_END=$(date +%s)
TEST_TIME=$(($TEST_END - $TEST_START))
echo -e "Ended QCS Test Suite : $(date)" | tee -a $OUTPUT_FILE
echo -e "Total testing time   : $TEST_TIME seconds\n" | tee -a $OUTPUT_FILE

# Avoids to close the shell window when this script is run from command line
# echo
# read -p "Press Enter to exit ... "
