#!/usr/bin/env bash

set -x

###---------------------------------------------------------------------------------###
###---                                                                           ---###
###--- Bash script wrapper for wtcm2grib2.f to write final output into           ---###
###--- grib2 format. Dissemination of output occurs here as well.                ---###
###---                                                                           ---###
###--- Usage: ./wtcm2grib2.bash indat.dat inref.asc gridID runCode dbnsubtype    ---###
###---                                                                           ---###
###--- where: 1) indat.dat  = binary input file name containing                  ---###
###---                        computational grid only                            ---###
###---        2) inref.asc  = ascii file containing required                     ---###
###---                        interpolation parameters                           ---###
###---        3) gridID     = AT, PR, ATOCEAN, EPAC, CPAC, etc.                  ---###
###---        4) runCode    = "prelim" or "final"                                ---###
###---        5) dbnsubtype = WTCM_PRELIM, WTCM_FINAL, or WTCM_ONDEMAND          ---###
###---                                                                           ---###
###--- VERSION: 1.0.3b                                                           ---###
###---                                                                           ---###
###--- Edit history:                                                             ---###
###---               Matt Onderlinde - Jan 2019 - wrote original code            ---###
###---               Matt Onderlinde - Nov 2019 - added CPAC domain              ---###
###---               Matt Onderlinde - Dec 2024 - adopted for WCOSS              ---###
###---                                                                           ---###
###---------------------------------------------------------------------------------###

###--- Define grib2 output file name identifier strings
AT_idstring=conus
PR_idstring=prsju
ATOCEAN_idstring=ocean
EP_idstring=conus
EPAC_idstring=ocean
CPAC_idstring=ocean
HFOE_idstring=hfoe
HFOC_idstring=hfoc

###--- Define grib2 template files for each grid
AT_g2template=${PARMwtcm}/WTCMAT_Template.grb2
PR_g2template=${PARMwtcm}/WTCMATpr_Template.grb2
ATOCEAN_g2template=${PARMwtcm}/WTCMATocean_Template.grb2
EP_g2template=${PARMwtcm}/WTCMEP_Template.grb2
EPAC_g2template=${PARMwtcm}/WTCMEPAC_Template.grb2
CPAC_g2template=${PARMwtcm}/WTCMCPAC_Template.grb2
HFOE_g2template=${PARMwtcm}/WTCMEPhfo_Template.grb2
HFOC_g2template=${PARMwtcm}/WTCMCPhfo_Template.grb2

###--- Define header letter for each grid
AT_headerSubgridLetter=S
PR_headerSubgridLetter=P
ATOCEAN_headerSubgridLetter=O
EP_headerSubgridLetter=S
EPAC_headerSubgridLetter=O
CPAC_headerSubgridLetter=O
HFOE_headerSubgridLetter=H
HFOC_headerSubgridLetter=H

###--- Define WMO header prefixes for each basin
ATheaderPrefixFinal=HWA
ATheaderPrefixPrelim=HMA
EPheaderPrefixFinal=HWB
EPheaderPrefixPrelim=HMB
CPheaderPrefixFinal=HWF
CPheaderPrefixPrelim=HMF

###--- Define the maximum number of allowed NHC storm bins per basin
maxBins=5

### NOTE: ${PARMwtcm} and ${EXECwtcm} are exported by run_wtcm_realtime.bash
### NOTE: Output files will look like this and are just listed here for reference
### nhc.wtcm.al##YYMMDDHH.ocean.final.grb2  - .04 deg res
### nhc.wtcm.al##YYMMDDHH.ocean.prelim.grb2 - .04 deg res
### nhc.wtcm.al##YYMMDDHH.conus.final.grb2  - .02 deg res
### nhc.wtcm.al##YYMMDDHH.conus.prelim.grb2 - .02 deg res
### nhc.wtcm.al##YYMMDDHH.prsju.final.grb2  - .01 deg res
### nhc.wtcm.al##YYMMDDHH.prsju.prelim.grb2 - .01 deg res
### nhc.wtcm.ep##YYMMDDHH.conus.final.grb2  - .02 deg res
### nhc.wtcm.ep##YYMMDDHH.conus.prelim.grb2 - .02 deg res
### nhc.wtcm.ep##YYMMDDHH.ocean.final.grb2  - .04 deg res
### nhc.wtcm.ep##YYMMDDHH.ocean.prelim.grb2 - .04 deg res
### nhc.wtcm.cp##YYMMDDHH.ocean.final.grb2  - .04 deg res
### nhc.wtcm.cp##YYMMDDHH.ocean.prelim.grb2 - .04 deg res
### nhc.wtcm.ep##YYMMDDHH.hfoe..final.grb2  - .01 deg res
### nhc.wtcm.ep##YYMMDDHH.hfoe.prelim.grb2  - .01 deg res
### nhc.wtcm.cp##YYMMDDHH.hfoc..final.grb2  - .01 deg res
### nhc.wtcm.cp##YYMMDDHH.hfoc.prelim.grb2  - .01 deg res

###-----------------------------------------------------------------------###
###-----------------------------------------------------------------------###

###--- Get command line arguments
datfile=${1}
reffile=${2}
gridname=${3}
runCode=${4}
dbnsubtype=${5}
if [ ${#dbnsubtype} -eq 0 ];then
	echo ""; echo "ERROR: Must pass in 5 arguments. See ${0} header for details."; echo ""
	exit
fi

###--- Process in temporary space
outputDir=outputCreation_${gridname}_`date "+%Y%m%d%H%M%S"`
mkdir ${outputDir}
cd    ${outputDir}
ln -sf ../* .

###--- Call Fortran with the provided arguments
rm wtcm_output_uv.dat wtcm_output_stats.dat 2> /dev/null
${EXECwtcm}/wtcm2grib2.x ${datfile} ${reffile} ${gridname} uv
mv wtcm_output.dat wtcm_output_uv.dat
datfile_stats=$( echo ${datfile} | sed -e 's/bin/gfd/g' )
${EXECwtcm}/wtcm2grib2.x ${datfile_stats} ${reffile} ${gridname} stats
mv wtcm_output.dat wtcm_output_stats.dat

###--- Determine byte length for each record
read ny nx <<< $( grep ${gridname} ${PARMwtcm}/wtcm_output_grid_defs | head -1 | cut -f 3,6 -d " " )
if [ ${#ny} -eq 0 ] || [ ${#nx} -eq 0 ];then
	echo ""; echo "ERROR: Could not properly identify requested grid dimensions."; echo ""
	rm -rf ${outputDir} 2> /dev/null
	exit
fi
nbytes_per_record=$(( ${nx} * ${ny} * 4 ))

###--- Determine number of forecast hours to process
nfhr=$( head -1 ${reffile} | sed -e 's/ \{1,\}/,/g' | cut -f 5 -d "," | cut -f 1 -d "." )
if [ ${#nfhr} -eq 0 ];then
	echo ""; echo "ERROR: Could not properly determine the number of forecast hours to process."; echo ""
	rm -rf ${outputDir} 2> /dev/null
	exit
fi

###--- Determine the model init time
init=$( head -1 ${reffile} | cut -f 2-4 -d " " | sed -e 's/ //g' )
if [ ${#init} -eq 0 ];then
	echo ""; echo "ERROR: Could not properly identify the model init time."; echo ""
	rm -rf ${outputDir} 2> /dev/null
	exit
fi
init_short=$( echo ${init} | cut -c 3-10 )

###--- Determine the TCID
tcidFull=$( head -1 ${reffile} | cut -f 1-2 -d " " | sed -e 's/ //g' | tr '[:upper:]' '[:lower:]' )
tcid=${tcidFull:0:4}

###--- Determine the bin number from the WTCM bin reference file
sBin=$( cat nhcWindBinReference_${tcidFull}.txt )

###--- For invests, determine if we can transmit output, and which bin we should actually place the storm in
transmitInvest=1
if [ $( echo "${tcid:2:2} > 89" | bc ) -eq 1 ];then
	if [ "${runCode}" == "prelim" ];then
		echo "Prelim Invest run detected: ${tcidFull}"
		for otherStorm in $( ls -d ../../[a-z][a-z][0-8][0-9]${tcidFull:4:4} 2> otherStorms.error | rev | cut -f 1 -d "/" | rev )
		do
			otherBin=$( cat ../../${otherStorm}/nhcWindBinReference_${otherStorm}.txt )
			if [ "${otherBin}" == "${sBin}" ];then
				echo "Bin conflict detected for ${tcidFull}. Matches ${otherStorm}. Will check for a different bin to put ${tcidFull} into..."
				foundBin=0
				for newBin in $(seq 1 1 ${maxBins})
				do
					checkBin=$( echo ${tcid:0:2} | sed -e 's/al/at/g' )${newBin}
					if [ $( grep "${checkBin}" ../../[a-z][a-z][0-8][0-9]${tcidFull:4:4}/nhcWindBinReference_*txt | wc -l ) -eq 0 ];then
						echo "Found bin ${checkBin} unoccupied. Will use it for ${tcidFull}."
						foundBin=1
						sBin=${checkBin}
						break
					fi
					if [ ${newBin} -eq ${maxBins} ] && [ ${foundBin} -eq 0 ];then
						echo "NOTICE: Unable to find an available bin for transmission of ${tcidFull}."
						transmitInvest=0
					fi
				done
			fi
		done
	else
		echo "NOTE: Non-prelim Invest output is not transmitted. TCID: ${tcidFull}"
		transmitInvest=0
	fi
fi

###--- Determine grid ID type, grib2 template, and WMO header
eval idstring=${gridname}_idstring
idstring=${!idstring}
eval g2template=${gridname}_g2template
g2template=${!g2template}
eval headerSubgridLetter=${gridname}_headerSubgridLetter
headerSubgridLetter=${!headerSubgridLetter}
if   [ ${sBin:0:2} == "at" ];then
	if [ ${runCode} == "final" ];then
		wmoHeader=${ATheaderPrefixFinal}${headerSubgridLetter}9${sBin:2:1}
	else
		wmoHeader=${ATheaderPrefixPrelim}${headerSubgridLetter}9${sBin:2:1}
	fi
elif [ ${sBin:0:2} == "ep" ];then
	if [ ${runCode} == "final" ];then
		wmoHeader=${EPheaderPrefixFinal}${headerSubgridLetter}9${sBin:2:1}
	else
		wmoHeader=${EPheaderPrefixPrelim}${headerSubgridLetter}9${sBin:2:1}
	fi
elif [ ${sBin:0:2} == "cp" ];then
	if [ ${runCode} == "final" ];then
		wmoHeader=${CPheaderPrefixFinal}${headerSubgridLetter}9${sBin:2:1}
	else
		wmoHeader=${CPheaderPrefixPrelim}${headerSubgridLetter}9${sBin:2:1}
	fi
fi

###--- Write the data out into grib2 format
standard_chunk=10
niterations=$(( $(( $(( ${nfhr} + 1 )) / ${standard_chunk} )) + 1 ))
fhr=0
for t in $(seq 1 1 ${niterations})
do
	rm curchunk_uv.dat curchunk_stats.dat 2> /dev/null
	if [ ${t} -eq ${niterations} ];then
		nchunk=$(( $(( ${nfhr} + 1 )) % ${standard_chunk} ))
	else
		nchunk=${standard_chunk}
	fi
	head -c $(( ${t} * ${nbytes_per_record} * 2 * ${standard_chunk} )) wtcm_output_uv.dat    | tail -c $(( ${nbytes_per_record} * 2 * ${nchunk} )) > curchunk_uv.dat
	head -c $(( ${t} * ${nbytes_per_record} * 2 * ${standard_chunk} )) wtcm_output_stats.dat | tail -c $(( ${nbytes_per_record} * 2 * ${nchunk} )) > curchunk_stats.dat
	for n in $(seq 1 1 ${nchunk})
	do
		rm currecs_uv.dat currecs_stats.dat 2> /dev/null
		if [ ${t} -eq 1 ] && [ ${n} -eq 1 ];then
			echo "${wmoHeader} KNHC ${init:6:4}00" >> ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2
		fi
		head -c $(( ${nbytes_per_record} * ${n} * 2 )) curchunk_uv.dat    | tail -c $(( ${nbytes_per_record} * 2 )) > currecs_uv.dat
		head -c $(( ${nbytes_per_record} * ${n} * 2 )) curchunk_stats.dat | tail -c $(( ${nbytes_per_record} * 2 )) > currecs_stats.dat
		wgrib2 ${g2template}       -no_header -import_bin currecs_uv.dat    -set_date ${init} -set_ftime "${fhr} hour fcst"  \
                                           -set background_process_id 255 -set analysis_or_forecast_process_id 10${sBin:2:1} -append \
                                           -set_grib_type c3 -grib_out ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2
		export err=$?; err_chk
		wgrib2 ${g2template}.stats -no_header -import_bin currecs_stats.dat -set_date ${init} -set_ftime "${fhr} hour fcst"  \
                                           -set background_process_id 255 -set analysis_or_forecast_process_id 10${sBin:2:1} -append \
                                           -set_grib_type c3 -grib_out ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2
		export err=$?; err_chk
		fhr=$(( ${fhr} + 1 ))
	done
done

###--- Keep an unheaded version of the file for dbnet transmission to NHC/OPC/WPC
tail -n +2 ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2 > ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.unheaded.grb2

###--- Prepend file byte size for SBN transmission (prelim & final)
if [ "${dbnsubtype}" == "WTCM_PRELIM" ] || [ "${dbnsubtype}" == "WTCM_FINAL" ];then
	fileSize=$( printf "%010d" $( wc -c ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2 | cut -f 1 -d " " ) | cut -c 1-10 )
	sed -i "1i****${fileSize}****" ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2
fi

###--- Transmission
if [ ${SENDCOM} = YES ]; then
	cp ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.unheaded.grb2  ${COMOUT}/nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2
	if [ ${SENDDBN} = YES ]; then
		if [ ${transmitInvest} -eq 1 ];then
			${DBNROOT}/bin/dbn_alert MODEL ${dbnsubtype} ${job} ${COMOUT}/nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2
		fi
	fi
	if [ "${dbnsubtype}" != "WTCM_ONDEMAND" ];then
		cp ../nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2  ${COMOUT_WMO}/
		if [ ${SENDDBN_NTC} = YES ]; then
			if [ ${transmitInvest} -eq 1 ];then
				${DBNROOT}/bin/dbn_alert NTC_LOW ${dbnsubtype} ${job} ${COMOUT_WMO}/nhc.wtcm.${tcid}${init_short}.${idstring}.${runCode}.grb2
			fi
		fi
	fi
fi
