#!/bin/bash
#
# Synchronizes the HAWC's Eye data on disk with the SQL database.
#
# The following scripts must be in the same directory as this script and 
# the named variables must be eddited in those files.
#	run-scripts.sh (this script)
# 		TEL
# 		DIR
# 		CRED
# 		CALLISTORC
# 		STARRC
# 	update-file-table2.sh
# 	extract-raw-header2.sh
#		FITSDUMP
# 	write-calibration-query.sh
# 	extract-aux-data2.sh
#		MARS
#		MACROS
# 	run-callisto2.sh
#		MARS
#		MACROS
# 	run-star2.sh
#		MARS
#		MACROS
# 	run-root2sql2.sh
#		ROOT2SQL
# 
# Example:
#	bash run-scripts.sh

set -o errexit
set -o errtrace
set -o nounset
set -o pipefail



function LockExit()
{
	echo "ERROR: One instance of ${SCRPTN} already running" >&2
	exit 1
}

function DescExit()
{
	echo "ERROR: Filedescriptor 200 already taken" >&2
	exit 1
}

function ErrExit()
{
	echo "ERROR: Line `caller`: ${BASH_COMMAND}" >&2
	exit 1
}

function StrgCExit()
{
	echo " "
	echo "$0 was forcefully terminated" >&2
	exit 1
}

trap ErrExit ERR
trap StrgCExit INT

# Telescope for which to process
readonly TEL="${1}"
if [ ${TEL} = "1" ]
then
	echo "Processing for Telescope 1"
elif [ ${TEL} = "2" ]
then
	echo "Processing for Telescope 2"
else
	echo "No valid Telescope selected!" >&2
	exit 1
fi

# Filename
readonly SCRPTN=`basename $0 .sh`

# For lockfile
readonly LOCK="/tmp/${SCRPTN}${TEL}.lock"

eval "exec 20${TEL}>${LOCK}" || DescExit
flock -n "20${TEL}" || LockExit

cd /home/hawc/Desktop/DiskToDB/

# For logfile
mkdir -p log
readonly DATE=`date +%Y%m%d_%H%M`
readonly LOG="./log/${SCRPTN}_${DATE}_${TEL}.log"
exec 3>&1 1>>${LOG}
exec 4>>${LOG}
exec 5>&2 2>>${LOG}
# exec 3>&1
# exec 4>&1

echo "Start processing data"

function DeleteEntries()
{
	# Delete entries form table ${3} for a given Telescope and Night
	# Arguments: Credentials Telescope Table Night
	local cred="${1}"
	local tel="${2}"
	local table="${3}"
	local night="${4}"

	mysql --defaults-file="${cred}" \
		--skip-column-names \
		--batch \
		--raw \
		--compress \
		-e "DELETE FROM ${table} WHERE Telescope = ${tel} \
		AND NIGHT = ${night};"
}

function SetStatus()
{
	# Status update for one Column, Night and Telescope
	# Arguments: Credentials Telescope Column Value Night
	local cred="${1}"
	local tel="${2}"
	local col="${3}"
	local val="${4}"
	local night="${5}"

	# Check if a valid Column was selected
	if [ ${col} != "header" ] \
		&& [ ${col} != "calibration" ] \
		&& [ ${col} != "auxiliary" ] \
		&& [ ${col} != "callisto" ] \
		&& [ ${col} != "star" ]
	then
		echo "ERROR: ${col} is not a valid column."
		exit 1
	fi

	mysql --defaults-file="${cred}" \
		--skip-column-names \
		--batch \
		--raw \
		--compress \
		-e "UPDATE DataOnDisk SET ${col} = ${val}\
		WHERE NIGHT = ${night} AND Telescope = ${tel};"
}

function GetStatus()
{
	# Return status of Night for a given Column and Telescope
	# Arguments: Credentials Telescope Column Night
	local cred="${1}"
	local tel="${2}"
	local col="${3}"
	local night="${4}"

	# Check if a valid Column was selected
	if [ ${col} != "header" ] \
		&& [ ${col} != "calibration" ] \
		&& [ ${col} != "auxiliary" ] \
		&& [ ${col} != "callisto" ] \
		&& [ ${col} != "star" ]
	then
		echo "ERROR: ${col} is not a valid column."
		exit 1
	fi

	local STATUS=`mysql --defaults-file="${cred}" \
		--skip-column-names \
		--batch \
		--raw \
		--compress \
		-e "SELECT DISTINCT ${col} FROM DataOnDisk \
		WHERE NIGHT = ${night} \
		AND Telescope = ${tel} \
		AND ${col} IS NULL;"`

	echo "${STATUS}"
}


function DoesDirExists()
{
	local thing="${1}"
	# Check if thing exists
	if [ ! -d "${thing}" ]
	then
		echo "${thing} is not a valid Path. Please change variable in script ${SCRPTN}."
		exit 1
	fi
}

function DoesFileExists()
{
	local thing="${1}"
	# Check if thing exists
	if [ ! -f "${thing}" ]
	then
		echo "${thing} is not a valid File. Please change variable in script ${SCRPTN}."
		exit 1
	fi
}

# Define variables
# Directory in which the raw directory is located
readonly DIR="/media/DATA/HAWCsEYE0${TEL}/"
# Credentials for the SQL database
readonly CRED='../Credentials/credentials-read-only.cnf'
# Credentials for root2sql for callisto
readonly CALLISTORC='../Credentials/root2sql-callisto.rc'
# Credentials for root2sql for star
readonly STARRC='../Credentials/root2sql-star.rc'
# ROOT init path
readonly RPATH='../root-6.24.02/bin/thisroot.sh'

echo "Processing data from ${DIR}"

# Check if variable paths point to something sensible
DoesDirExists "${DIR}"
DoesFileExists "${CRED}"
DoesFileExists "${CALLISTORC}"
DoesFileExists "${STARRC}"
DoesFileExists "${RPATH}"

# SQL outputs
mkdir -p ./queries
readonly ONDISK="./queries/insert-OnDisk-${TEL}.sql"
readonly AUXDISK="./queries/insert-AuxOnDisk-${TEL}.sql"
readonly RAW="./queries/insert-raw-${TEL}.sql"
readonly CALIB="./queries/find-calibration2-${TEL}.sql"
readonly AUX="./queries/insert-aux-${TEL}.sql"

# Init ROOT
set +o nounset
. "${RPATH}"
set -o nounset

# Create Database of existing files
echo "Updating file table"
bash ./update-file-table2.sh -i -o "${ONDISK}" "${TEL}" "${DIR}/raw"
# Update DataOnDisk tabel in database
echo "Uploading updated table"
mysql --defaults-file="${CRED}" < "${ONDISK}"

# Create Database of existing auxiliary files
bash ./update-aux-table.sh -r -o "${AUXDISK}" "${TEL}" "${DIR}/auxil"
# Update DataOnDisk tabel in database
echo "Uploading updated table"
mysql --defaults-file="${CRED}" < "${AUXDISK}"

# get list of NIGHTS with unprocessed files
echo "Getting nights to be processed"
NIGHTS=`mysql --defaults-file="${CRED}" \
	--skip-column-names \
	--batch \
	--raw \
	--compress \
	-e "SELECT DISTINCT NIGHT FROM DataOnDisk \
	WHERE header IS NULL \
	OR calibration IS NULL \
	OR auxiliary IS NULL \
	OR callisto IS NULL \
	OR star IS NULL \
	AND Telescope = ${TEL};"`

# Check if NIGHTS is empty and dont do anythin if so.
if [ -z "${NIGHTS}" ]
then
	echo "Database is up to date. Nothing to do here."
	exit 0
fi

echo "Updating database"

echo "Nights to process:"
echo "${NIGHTS}"
echo " "


# Execute scripts on all RunId for given Telescope and Night that has
# Loop over nights and upload to database for every loop
for NIGHT in ${NIGHTS}
do
	HEAD_S=`GetStatus ${CRED} ${TEL} "header" ${NIGHT}`
	CALI_S=`GetStatus ${CRED} ${TEL} "calibration" ${NIGHT}`
	AUXI_S=`GetStatus ${CRED} ${TEL} "auxiliary" ${NIGHT}`
	CALL_S=`GetStatus ${CRED} ${TEL} "callisto" ${NIGHT}`
	STAR_S=`GetStatus ${CRED} ${TEL} "star" ${NIGHT}`

	echo "header = ${HEAD_S} for night = ${NIGHT}"
	echo " "

	# If header is null
	if [ ! -z ${HEAD_S} ] && [ ${HEAD_S} = "NULL" ]
	then
		# Get raw data headers
		echo "== In Status 1 =="
		bash ./extract-raw-header2.sh -d -o "${RAW}" \
			${TEL} \
			"${DIR}"/raw \
			${NIGHT}
		echo "Uploading raw headers for night: ${NIGHT}"
		mysql --defaults-file="${CRED}" < "${RAW}"
		echo "Finished uploading raw headers for night: ${NIGHT}"
		echo " "
	fi

	echo "calibration = ${CALI_S} for night = ${NIGHT}"
	echo " "

	# If header is null and or calibration is null
	if ([ ! -z ${HEAD_S} ] && [ ${HEAD_S} = "NULL" ]) \
		|| ([ ! -z ${CALI_S} ] && [ ${CALI_S} = "NULL" ])
	then
		# Get calibration files
		echo "== In Status 2 =="
		bash ./write-calibration-query.sh -d -o "${CALIB}" \
			${TEL} \
			${NIGHT}
		echo "Uploading calibration for night: ${NIGHT}"
		mysql --defaults-file="${CRED}" < "${CALIB}"
		echo "Finished uploading calibration for night: ${NIGHT}"
		echo " "
	fi

	echo "auxiliary = ${AUXI_S} for night = ${NIGHT}"
	echo " "

	# If header is null and or calibration is null and or auxiliary is null
	if ([ ! -z ${HEAD_S} ] && [ ${HEAD_S} = "NULL" ]) \
		|| ([ ! -z ${CALI_S} ] && [ ${CALI_S} = "NULL" ]) \
		|| ([ ! -z ${AUXI_S} ] && [ ${AUXI_S} = "NULL" ])
	then
		# Get aux data
		echo "== In Status 3 =="
		bash ./extract-aux-data2.sh -d -o "${AUX}" \
			${CRED} \
			${TEL} \
			"${DIR}"/auxil \
			${NIGHT}
		echo "Uploading aux data for night: ${NIGHT}"
		mysql --defaults-file="${CRED}" < "${AUX}"
		echo "Finished uploading aux data for night: ${NIGHT}"
		echo " "
	fi

	echo "callisto = ${CALL_S} for night = ${NIGHT}"
	echo " "

	# If header is null and or calibration is null and or callisto is null
	if ([ ! -z ${HEAD_S} ] && [ ${HEAD_S} = "NULL" ]) \
		|| ([ ! -z ${CALI_S} ] && [ ${CALI_S} = "NULL" ]) \
		|| ([ ! -z ${CALL_S} ] && [ ${CALL_S} = "NULL" ])
	then
		# Get callisto data
		echo "== In Status 4 =="
		bash ./run-callisto2.sh -r \
			"${CRED}" \
			${TEL} \
			"${DIR}"/raw \
			${NIGHT}

		echo "Deleting callisto entries for night: ${NIGHT}"
		DeleteEntries ${CRED} ${TEL} "Callisto" ${NIGHT}

		echo "Uploading callisto entries for night: ${NIGHT}"
		bash ./run-root2sql2.sh -Y \
			"${CRED}" \
			"${CALLISTORC}" \
			${TEL} \
			"${DIR}"/callisto \
			${NIGHT}
		echo "Finished uploading callisto entries for night: ${NIGHT}"
		echo " "
	fi

	echo "star = ${STAR_S} for night = ${NIGHT}"
	echo " "

	# If header is null and or calibration is null and or callisto is null
	# and or star is null
	if ([ ! -z ${HEAD_S} ] && [ ${HEAD_S} = "NULL" ]) \
		|| ([ ! -z ${CALI_S} ] && [ ${CALI_S} = "NULL" ]) \
		|| ([ ! -z ${CALL_S} ] && [ ${CALL_S} = "NULL" ]) \
		|| ([ ! -z ${STAR_S} ] && [ ${STAR_S} = "NULL" ])
	then
		# Get star data
		echo "== In Status 5 =="
		bash ./run-star2.sh -r "${CRED}" ${TEL} "${DIR}"/raw ${NIGHT}

		echo "Deleting star entries for night: ${NIGHT}"
		DeleteEntries ${CRED} ${TEL} "Star" ${NIGHT}

		echo "Uploading star entries for night: ${NIGHT}"
		bash ./run-root2sql2.sh -I \
			"${CRED}" \
			"${STARRC}" \
			${TEL} \
			"${DIR}"/star \
			${NIGHT}
		echo "Finished uploading star entries for night: ${NIGHT}"
		echo " "
	fi

done

echo " "
echo "Finished processing data"
