#!/bin/ksh

set +x
#####################################################################
echo "-------------------------------------------------------"
echo "hwrf_tpcpost.sh - Script to run HWRF post-processing of TPC text "
echo "                  and wind & rainfall swath files"
echo "-------------------------------------------------------"
echo "History: JUN 1997 - First implementation of this new script."
echo "         JAN 1998 - Rewritten by David Michaud to standardize"
echo "         AUG 1998 - Modified by Peter Henrichsen to use script"
echo "                    onebul.sh to make and send storm bulletin."
echo "         NOV 2000 - Modified by Peter Henrichsen to replace "
echo "                    onebul.sh with formbul.pl."
echo "         MAR 2001 - Tim Marchok added save of stats.short file"
echo "                    to STOREhur directory, plus coupled plots"
echo "         JAN 2006 - L. Sager  Modified to use form_ntc.pl to  "
echo "                    send bulletins to TOC via NTC         "
echo "         APR 2007 - Tuleya adapted GFDL TPC text scripts & added"
echo "                    added swath function by reading auxiliary files"
echo "         APR 2007 - Implemented For HWRF Operations"
echo "                    Vijay Tallapragada"
echo "         JUN 2009 - Revised for HWRF 2009 implementation, Vijay Tallapragada"
echo "         OCT 2010 - Modified for HWRF V3 by Sam Trahan."
echo "         JUN 2011 - Added support for HTCF output -- Sam Trahan."
#####################################################################
set -x

#--------------------------------------------------------------------------
# USAGE:   sh hwrf_tpcpost.sh STORM PDY cyc stormid CASE MODEL domain
# EXAMPLE: sh hwrf_tpcpost.sh PHILIPPE 20050917 18 17L FCST COUPLED COMBINE
#--------------------------------------------------------------------------

if [[ PARAFLAG == YES ]] ; then
    ABORT_IF_TPCPOST_FAILS=YES # see below for explanation of this.
fi

function fail {
    # This function is called when this script encounters a fatal error.
    # It prints its arguments to stdout and stderr and then either
    # exits hwrf_tpcpost.sh or llcancels the entire job.

    # If we're in operations mode, this function will call err_exit,
    # killing the entire loadleveler job. 

    # If we're in development mode (PARAFLAG=YES), then you can
    # prevent the killing of the loadleveler job by setting the
    # variable ABORT_IF_TPCPOST_FAILS to NO.  This allows the
    # kick_scripts (SMS replacement) to submit the output job
    # even if parts of the tpcpost fail.

    echo "$*"      # send message to stdout
    echo "$*" 1>&2 # send message to stderr

    if [[ "$PARAFLAG" == YES && "$ABORT_IF_TPCPOST_FAILS" == NO ]] ; then
        exit 1  # exit tpcpost, but do not kill job
    fi

    sh ${utilscript}/setup.sh
    if [[ -z "$err" ]] ; then
        # Set a default error status if none is present
        err=911
    fi
    export err
    err_exit "$*"
}

function htcffail {
    # This function is called when an HTCF-related product is not
    # correctly produced.  It aborts in PARA mode, but not in
    # operational mode.
    msg="$*"
    if [[ "$PARAFLAG" == YES ]] ; then
        fail "$msg"
    else
        postmsg "$jlogfile" "$msg -- continuing anyway without experimental HTCF products"
    fi
}

####### GET THE INPUT VARIABLES ###################
if [ $# -eq 7 ] ; then 
    STORM=$1
    PDY=$2
    cyc=$3  
    stormid=$4
    case=$5
    model=$6
    domain=$7

    echo 'STORM   = ' ${STORM}
    echo 'PDY     = ' ${PDY}
    echo 'cyc     = ' ${cyc} 
    echo 'stormid = ' ${stormid}
    echo 'case    = ' ${case}
    echo 'model   = ' ${model}
    echo 'domain  = ' ${domain} 
    export PDY
    export cyc  
else
    echo 'USAGE:   sh hwrf_tpcpost.sh STORM PDY cyc stormid CASE MODEL domain'
    echo 'EXAMPLE: sh hwrf_tpcpost.sh RITA  20050919 12 18L FCST COUPLED COMBINE'   
    echo 'NEED SEVEN ARGUMENTS'
    echo 'SCRIPT WILL EXIT'
    fail 'HWRF_TPCPOST.SH NEEDS SEVEN ARGUMENTS'
    exit 1
fi  
###################################################
# set the paths

export CSTREAM=${CSTREAM} 
if [[ "$OLD_TRACKER" == YES ]] ; then
    if [[ -d $CSTREAM/${model}_FCST/trakout.FCST.COMBINE ]] ; then
        export VITALSPATH=$CSTREAM/${model}_FCST/trakout.FCST.COMBINE
    elif [[ -d $CSTREAM/${model}_FCST/trakout.FCST_FCST.COMBINE ]] ; then
        export VITALSPATH=$CSTREAM/${model}_FCST/trakout.FCST_FCST.COMBINE
    else
        fail 'UNABLE TO FIND VITALSPATH DIRECTORY.  TRIED:' $CSTREAM/${model}_FCST/trakout.FCST.COMBINE $CSTREAM/${model}_FCST/trakout.FCST_FCST.COMBINE
    fi
fi
export FCSTPATH=$CSTREAM/${model}_FCST
export hwrf_dir=$CSTREAM/${model}_FCST/COMBINE
TMPDIR=${hwrf_dir}/TMPDIR

echo 'CSTREAM    = ' ${CSTREAM}
if [[ "$OLD_TRACKER" == YES ]] ; then
    echo 'VITALSPATH = ' ${VITALSPATH}
fi
echo 'FCSTPATH   = ' ${FCSTPATH}  
echo 'hwrf_dir   = ' ${hwrf_dir}  
echo 'TMPDIR     = ' ${TMPDIR}
echo 'COMOUT     = ' ${COMOUT}  



###################################################################
# Determine NHC atcf name
###################################################################
snum=`echo $stormid | cut -c1-2`
bas=` echo $stormid | cut -c3` 

echo 'snum = ' ${snum}
echo 'bas  = ' ${bas}  

case $bas in
    L) basin="AL";;
    E) basin="EP";;
    C) basin="CP";;
    W) basin="WP";;
    [AB]) basin="IO" ;;
    [PS]) basin="SH" ;;
    Q) basin="SL" ;;
    *) :;;
esac

YY=`echo $PDY | cut -c3-4`
export ATCFNAME="$basin$snum"

echo 'basin    = ' ${basin}
echo 'ATCFNAME = ' ${ATCFNAME}

export stormenv=${STORM}${stormid}
export YMDH=${PDY}${cyc}
YYMMDD=`echo ${PDY} | cut -c3-8`
stormlabel=${STORM}${PDY}
export pgmout=$hwrf_dir/pgmout
export SENDCOM=YES

rm -rf ${TMPDIR}
mkdir -p ${TMPDIR} 
cd $TMPDIR   

# Delete the two files the hwrf_output waits for since
# we're restarting (or starting) the tpcpost:
rm -f $hwrf_dir/$stormenv.${YMDH}.no.storm \
      $hwrf_dir/$stormenv.${YMDH}.stats.short

#########################################################################
# Make the final HTCF file and copy it to /com
########################################################################

if [[ -z "$ATMOS_DOMAINS" ]] ; then
    fail PLEASE SET \$ATMOS_DOMAINS
fi

if [[ "$PARAFLAG" == YES ]] ; then
    submodel=PARA
else
    submodel=OPER
fi

HTCFMODEL=${HTCFMODEL:-${TRACKMODEL:-HWRF}}
prepend="$basin, $snum, ${YMDH}00, ${HTCFMODEL}, ${submodel}, "

inhtcf=$CSTREAM/${model}_FCST/hifreq_d0${ATMOS_DOMAINS}.htcf
outhtcf=$COMOUT/$stormenv.$YMDH.hwrf_d0${ATMOS_DOMAINS}.htcf

nohtcf=NO

if [[ ! -s "$inhtcf" ]] ; then
    htcffail "WRF did not produce HTCF file: $inhtcf"
    nohtcf=YES
else
    cat "$inhtcf" | sed "s:^:$prepend:g" > "$outhtcf"

    if [[ ! -s "$outhtcf" ]] ; then
        htcffail "Final HTCF file is empty or non-existant: $outhtcf"
        nohtcf=YES
    else 
        if [ "$SENDDBN" = 'YES' ] ; then
           $DBNROOT/bin/dbn_alert MODEL HWRF_ASCII $job "$outhtcf"
        fi
    fi
fi

#########################################################################
# Now deal with the ATCF file
########################################################################

#---- first convert unix file to GFDL "stats" type ---------------

if [[ "$OLD_TRACKER" == YES ]] ; then
    track126=${CSTREAM}/${MODEL}_FCST/COMBINE/trak.hwrf.atcfunix.${YYYYMMDDHH}
else
    basename=$( echo trak.hwrf.atcfunix.$STORM$ATCFID.${YYYYMMDDHH} | tr A-Z a-z )
    if [[ "$ATMOS_DOMAINS" == 3 ]] ; then
        track126=${CSTREAM}/TRACK/3km/trak/$basename
    else
        track126=${CSTREAM}/TRACK/9km/trak/$basename
    fi
fi

if [ -s $track126 ]
    then 
    cp $track126  hwrf.atcfunix
else
    fail "FILE $track126 NOT PRESENT.  ABORTING"
fi

# run the executable hwrf_atcf_to_stats  
sh ${utilscript}/setup.sh 
export pgm=hwrf_atcf_to_stats
. prep_step
startmsg
${EXEChwrf}/hwrf_atcf_to_stats  
export err=$?; err_chk
echo "executable hwrf_atcf_to_stats return code err = ${err}"  
if [ $err -ne 0 ]; then
    fail "executable hwrf_atcf_to_stats return code err = ${err}.  ABORTING"
fi


FINALHR=`tail -1 hwrf.stats | cut -c6- | awk '{print $1}' `

cp hwrf.stats                          ./$stormenv.${YMDH}.stats.short
if [[ "$OLD_TRACKER" == YES ]] ; then
    cp $VITALSPATH/vitals.upd.hwrf.$YMDH   ./
else
    cp $CSTREAM/MESSAGES/storm_vit ./vitals.upd.hwrf.$YMDH
fi
cut -c1-19,22- vitals.upd.hwrf.$YMDH > ${ATCFNAME}.vitals.${YMDH}    

label="cat $hwrf_dir/$stormlabel.$cyc"

if test -f "$label" = "No $stormlabel"
    then
   ##############################################
   # Condition if no storms are to be run
   ##############################################
    msg="No hurricane to run."
    postmsg "$jlogfile" "$msg"

    exit
fi

#########################################################################
# Run the htcfstats program to get combined ATCF/HTCF information
########################################################################

if [[ "$nohtcf" != YES ]] ; then
    hstat_prefix=$COMOUT/$stormenv.$YMDH.hwrf_d0${ATMOS_DOMAINS}
    $EXEChwrf/hwrf_htcfstats "$track126" "$outhtcf" "$hstat_prefix"
    hstat_file="$hstat_prefix.htcfstats"
    if [[ ! -s "$hstat_file" ]] ; then
        htcffail "$hstat_file: hwrf_htcfstats output file is missing or empty"
        nohtcf=YES
    fi
fi

if [[ "$nohtcf" != YES ]] ; then
    # Generate a resolution summary file based on the htcfstats
    res_summary=$COMOUT/$stormenv.$YMDH.resolution
    cat "$hstat_file" | awk '
      BEGIN {
        print "BS, ID,      CYCLE, MT, MODL, HR1, HR2, RESKM, MAXDIST, MOVES"
      } {
        if($15<250) {
          res="3"
        } else if($15<450) {
          res="9"
        } else {
          res="27"
        };
        printf "%s, %5d, %7d, %5d\n", substr($0,1,38), res, $11, $10
      }' > "$res_summary"
    if [[ ! -s "$res_summary" ]] ; then
        htcffail "$res_summary: file is missing or empty"
        nohtcf=YES
    fi
    lines=$( echo $( wc -l < "$res_summary" ) )
    if [[ ! ( "$lines" -gt 1 )  ]] ; then
        htcffail "$res_summary: file has no data (fewer than 2 lines present)"
        nohtcf=YES
    fi
fi

########################################################################
# Make the Tier I file
########################################################################

# IMPORTANT: This IF statement MUST match what is in hwrf_output.sh
if [[ "$PARAFLAG" == YES ]] ; then
    TRACKMODEL=${TRACKMODEL:-HWRF}
    SUBMODEL=${SUBMODEL:-PARA}
    if [[ "$CASE_ROOT" == FORECAST ]] ; then
        dh=d
    else
        dh=h
    fi
else
    TRACKMODEL=HWRF
    SUBMODEL=OPER
    dh=d
fi

TierI=$COMOUT/a$( echo "$basin" | tr '[A-Z]' '[a-z]' )$( echo "$stormid" | cut -c1-2)$( echo "$PDY" | cut -c1-4 )_${TRACKMODEL}_${dh}${SUBMODEL}_$PDY$CYC.dat

if [[ ! -s $track126 ]] ; then
    # Track file exists but is empty, so produce an empty Tier I file
    cat /dev/null > "$TierI"
else
    cat "$track126" | cut -c1-112 | sed "s,HWRF,$TRACKMODEL,g" > "$TierI"
fi

#########################################################################
# Make the AFOS file and copy it to /com space.
# Bring in the NHC vitals file for the initial position:
########################################################################

cp $FCSTPATH/MDstatus .
#  Determine whether running coupled or uncoupled HWRF
if [ $model == COUPLED ]; then
    echo '1' > coupled_status.${ATCFNAME}.${PDY}${cyc}
else
    echo '0' > coupled_status.${ATCFNAME}.${PDY}${cyc}            
    echo "FORECAST WAS RUN UNCOUPLED..." > oceanstatus.txt 
fi

#
if [ -s MDstatus ]; then
#if [ -s ./MDstatus ]; then
    ostatus=`wc MDstatus | cut -c8`
    echo $ostatus

    if [ -s $COMOUT/restart_status.${STORM}${STORMID}.${YYYYMMDDHH} ]; then
        echo "Model run has a Restart" 
        . $COMOUT/restart_status.${STORM}${STORMID}.${YYYYMMDDHH}
        echo $RESTART
        echo $restart_start_hr
        if [ $RESTART == SUCCESS ]; then
            echo "FORECAST WAS RUN UNCOUPLED from $restart_start_hr using Restart Options" >>oceanstatus.txt
        else
            echo "FORECAST WAS RUN UNCOUPLED from $restart_start_hr but failed to complete 126 hr integration" >>oceanstatus.txt
        fi
    fi

    if [ $ostatus == 0 ]; then
        echo "FORECAST WAS RUN COUPLED FOR THE ENTIRE PERIOD..." >>oceanstatus.txt

    else
        HRUNC=` cat MDstatus | cut -c 13-21`
        echo "    FORECAST RAN COUPLED TO HOUR: " $HRUNC   >> oceanstatus.txt
    fi
else
    echo "MODEL RUN WAS UNCOUPLED"
    echo "    FORECAST RAN UNCOUPLED"  >> oceanstatus.txt
fi
#


# run executable hwrf_afos
sh ${utilscript}/setup.sh  
export pgm=hwrf_afos
. prep_step

ln -s -f coupled_status.${ATCFNAME}.${PDY}${cyc}  fort.2
ln -s -f ${ATCFNAME}.vitals.${YMDH}               fort.11
ln -s -f $stormenv.${YMDH}.stats.short            fort.12
ln -s -f $stormenv.${YMDH}.afos                   fort.51

startmsg
$EXEChwrf/hwrf_afos >> $pgmout 2>errfile
export err=$?;err_chk
echo "executable hwrf_afos return code err = ${err}"  

if [ $err -ne 0 ]; then
    fail  "executable hwrf_afos return code err = ${err}"
fi

if [ $FINALHR -lt 120. ] ; then
    echo "    STORM DISSIPATED AT $FINALHR HOURS AT ABOVE POSITION." >> $stormenv.${YMDH}.afos
fi


########################################################################
# Run awk code on the stats.complete file to determine how long
# the forecast ran coupled.  The key is the 7th element in the 
# line, which is also currently the last element in the line.  That 
# element indicates the average cooling of the SST's within a certain 
# radius of the storm center.  If that number is exactly zero, then 
# that indicates that the forecast is no longer running coupled.
# A message is output indicating the length of time that the model
# ran coupled, and this message will be appended to the bottom of
# the stats.tpc message file.
########################################################################

########################################################################
# Reformat the stats.short file to include a header and to reformat
# the output to fit in column form in less than 73 characters across.
# We will use the top 8 lines of the header directly from the afos 
# file just created, so obviously it is vital that this stuff always
# be placed AFTER the afos program.  This reformatting was requested
# by TPC because the whole width of the stats.short was too wide for
# their printers.  Note that there are 2 awk statements.  The first 
# is to add a space between "HOUR:" and the hour value and to add a 
# space between "(KNOTS):" and the wind value, in case these values 
# exceed 100.  The second awk statement is to check to see if the
# storm dissipated and, if so, to write a message to that effect.
########################################################################

sed -n 1,8p $stormenv.${YMDH}.afos >newstats
echo "FORECAST POSITIONS (FROM STATS.SHORT FILE...)" >>newstats
echo "                                             " >>newstats
echo "HOUR     LATITUDE    LONGITUDE    MIN PRESS (hPa)     MAX SFC WIND (KTS)" >>newstats
echo "                                             " >>newstats

awk '{ printf ("%s %s %s\n",substr($0,1,5),substr($0,6,84),substr($0,90))}' $stormenv.${YMDH}.stats.short >>newstats

if [ $FINALHR -lt 120. ] ; then
    echo "    STORM DISSIPATED AT $FINALHR HOURS AT ABOVE POSITION." >> newstats
fi


cat oceanstatus.txt               >>newstats
cat ${FIXhwrf}/hwrf_disclaimer.txt >>newstats

if test $SENDCOM = 'YES'
    then
    cp newstats $stormenv.${YMDH}.stats.tpc
fi

########################################################################
# Copy the afos file back to the com location
# Copy bulletin to /com directory
# Copy the modified TPC stats file to the com location
########################################################################
cp $stormenv.${YMDH}.afos $stormenv.${YMDH}.afos.nodisc

sed -n 1,7p   $stormenv.${YMDH}.afos >$stormenv.${YMDH}.afostemp.part1
sed -n 8,"$"p $stormenv.${YMDH}.afos >$stormenv.${YMDH}.afostemp.part2
cat $stormenv.${YMDH}.afostemp.part1 \
    ${FIXhwrf}/hwrf_disclaimer.txt    \
    $stormenv.${YMDH}.afostemp.part2 >$stormenv.${YMDH}.afos

if test $SENDCOM = 'YES'
    then
    cp $stormenv.${YMDH}.afos      $COMOUT/$stormenv.${YMDH}.afos
## cp $stormenv.${YMDH}.afos      $COMOUT/whxx04.$cycle.$stormenv
    cp $stormenv.${YMDH}.stats.tpc $COMOUT/$stormenv.${YMDH}.stats.tpc

    if [ "$SENDDBN" = 'YES' ] ; then
        $DBNROOT/bin/dbn_alert MODEL HWRF_STATS $job $COMOUT/$stormenv.${YMDH}.stats.tpc
        $DBNROOT/bin/dbn_alert MODEL HWRF_AFOS $job $COMOUT/$stormenv.${YMDH}.afos
    fi
    
fi

#########################################################################

#########################################################################
# create the storm bulletin by using form_ntc.pl
# to make and send the bulletin
#########################################################################
#########################################################################

# now create swath data by following meshes over fine-res parent domain
# use auxilary files
# First check to see if forecast length is greater than 6 hrs as reported
# in the tracker atcfunix file.

if [ $FINALHR -lt 06 ]; then
    echo "Storm died at $FINALHR; can't generate swaths for max. wind or precip"
    echo "This script exits without producing swath files"
    echo "Model run did not produce track beyond six hours.  No storm bulletin can be generated" >> new_stats
    echo "NO STORM" > $hwrf_dir/$stormenv.${YMDH}.no.storm
    sh ${utilscript}/setup.sh
    postmsg "$jlogfile" "Storm died at $FINALHR; can't generate swaths for max. wind or precip; exiting"
    exit 2
fi

#first create fine-resolution parent domain
mkdir $TMPDIR/swath
cd $TMPDIR/swath

cp $CSTREAM/${model}_FCST/domain.center ./
cp ../fort.12  ./

ln -s -f     domain.center      fort.10

# run the executable hwrf_gridgenfine
sh ${utilscript}/setup.sh  
export pgm=hwrf_gridgenfine
. prep_step
startmsg
${EXEChwrf}/hwrf_gridgenfine  
export err=$?
# err_chk
echo "executable hwrf_gridgenfine return code err = ${err}"  
if [ $err -ne 0 ]; then
    fail "executable hwrf_gridgenfine return code err = ${err}"
fi

# copy in aux file names.... 2-127  & aux files  of nest
rm -f domain.center fort.10
if ( ! $USHhwrf/hwrf_file_complete.pl -S15 -s1 -w600 -o10 $CSTREAM/WAVEM_d03/out4wave_d03 ) ; then
    echo 'There is a problem with the aux script, $CSTREAM/WAVEM_d03/out4wave_d03w file not created after ten minutes of waiting'
    echo 'Check if the model is running fine, now exiting'
    exit 1   # should NOT call fail() here -- 2010 HWRF does not err_exit here
fi

if [ -s $CSTREAM/WAVEM_d03/out4wave_d03 ]; then
    echo $CSTREAM/WAVEM_d03/out4wave_d03 available
else
    echo "don't know what to do"
fi

cp ${PARMhwrf}/hwrf_imjmuv10hlatlon_names fort.66
# BUG!!    cp $CSTREAM/WAVEM_d03/[123456789]* .
# Relies on filesystem ordering of files, breaks on Jet.  Do this instead:
for x in $( seq 1 127 ) ; do
    cp $CSTREAM/WAVEM_d03/$x .
done
#cp $CSTREAM/WAVEM_d03/[123456789]* .

# run the executable hwrf_swath
sh ${utilscript}/setup.sh 
export pgm=hwrf_swath
. prep_step
startmsg
${EXEChwrf}/hwrf_swath
export err=$?; err_chk
echo "executable hwrf_swath return code err = ${err}"  
if [ $err -ne 0 ]; then
    fail "executable hwrf_swath return code err = ${err}"
fi

### output units 76 & 77 are the swaths of wind10 and rainfall in ascii
##output unit 88 is the grads output for plotting wind10 and rainfall

cp fort.76 $hwrf_dir/$stormenv.${YMDH}.wind10m.ascii
cp fort.77 $hwrf_dir/$stormenv.${YMDH}.rainfall.ascii
cp fort.78 $hwrf_dir/$stormenv.${YMDH}.wind10hrly.ascii
cp fort.88 $hwrf_dir/$stormenv.${YMDH}.swath.dat

f88="$stormenv.${YMDH}.swath.dat"
cat swath.ctl | sed "s:fort.88:${f88}:" > swath.ctl.tmp

finalctl=$hwrf_dir/$stormenv.${YMDH}.swath.ctl
if [[ "$( $USHhwrf/hwrf_port_byteorder.sh )" == littleendian ]] ; then
    cp -pf swath.ctl.tmp "$finalctl"
else
    cat swath.ctl.tmp | grep -vi byteswap > "$finalctl"
fi

cp ${TMPDIR}/$stormenv.${YMDH}.stats.tpc $hwrf_dir/$stormenv.${YMDH}.stats.tpc
cp ${TMPDIR}/$stormenv.${YMDH}.afos $hwrf_dir/$stormenv.${YMDH}.afos
cp ${TMPDIR}/$stormenv.${YMDH}.stats.short $hwrf_dir/$stormenv.${YMDH}.stats.short



# end of script 
