#! /bin/ksh

set -x

function die {
    sh ${utilscript}/setup.sh
    err=911
    echo "$*"
    err_exit "$*"
    exit 2
}

if [[ "$#" != 10 ]] ; then
    cat<<EOF
ERROR.  Syntax:
  $0 firsthour lasthour increment STORM STORMID YYYYMMDDHH \\
       post-mode /path/to/wrfdir/ cenla cenlo

where:
  firsthour, lasthour -- first and last hours to post (no leading zeros)
  increment -- number of hours between forecast hours: 3 or 6
  STORM -- storm name, all capitals (ie.: KARL)
  STORMID -- storm id, all capitals (ie.: 13L)
  YYYYMMDDHH -- cycle number as a ten digit date (ie.: 2010091418)
  post-mode -- SAT for satellite products, or
               NOSATE for everything else
  /path/to/wrfdir -- path to the COUPLED_FCST or ATMOS_FCST directory
  cenla, cenlo -- center latitude and longitude of the post domain

Example:

  First cycle of 2010 Karl 13L, only satellite products, 6hourly:

  $0 \\
    0 126 6 KARL 13L 2010091418 SAT \\
    /ptmp/$USER/hwrf/2010091418/13L/KARL.2010091418/COUPLED_FCST \\
    18.1 -88.6
EOF
    die SCRIPT IS ABORTING BECAUSE 10 ARGUMENTS ARE REQUIRED
fi

firsthour="${1:-${POST_FIRSTHOUR:-0}}"
lasthour="${2:-${POST_LASTHOUR:-126}}"
increment="${3:-${POST_INCREMENT:-3}}"
STORM="${4:-$STORM}"
STORMID="${5:-$STORMID}"
ymdh="${6:-YYYYMMDDHH}"
POST_MODE="$7" # SAT, NONSAT or BOTH
wrfdir="$8"
cenla="$9"
cenlo="${10}"

storm=$STORMNAME
DATE=$ymdh
CYC=$( echo "$ymdh" | cut -c9-10 )

export CSTREAM="${CSTREAM:-${DATA}/${STORM}.$ymdh}"

minage=30 # min wrfout file age in seconds

ndate=${NDATE_PATH:-${utilexec:-${NWPROD}/util/exec}/ndate}
wgrib=${WGRIB_PATH:-${utilexec:-${NWPROD}/util/exec}/wgrib}

if [[ "$PARAFLAG" != YES ]] ; then
    USHhwrf=${USHhwrf:-${NWPROD}/hwrf.${HWRF_VERSION}/ush/}
fi

if [[ "$POST_MODE" == SAT ]] ; then
    # In satellite mode, we only used d01 and d02 to make the
    # combined (hwrfsat_c) files (-2):
    more_opts='-2'
else
    # In non-satellite mode, we don't copy the satellite lookup files (-n),
    # but we use d01, d02 and d03 to make the combined (hwrfprs_c)
    # files (no -2):
    more_opts='-n'
fi

#----------------------------------------------------------------------#
# Turn on some variables requested by IBM helpdesk for debugging       #
#----------------------------------------------------------------------#

if [[ "$POST_MODE" == SAT ]] ; then  # ONLY TURN ON FOR SATELLITE POST

    # These debug settings will hopefully help us figure out why the
    # CRTM is crashing.  It is advisable to turn this on for NAM and
    # GFS, as well as any other models that use the new CRTM with the
    # new universal post.

    #BSM - for extra debug information asked for by IBM
    export MP_LABELIO=yes
    #BSM 20091022
    export MP_INFOLEVEL=6 # or higher
    export MP_S_DEBUG=4 # to force job core dump
    export MP_S_ENABLE_ERR_PRINT=yes
    export LAPI_DEBUG_COMM_TIMEOUT=yes
    export LAPI_DEBUG_PERF=yes
    export MP_COREFILE_FORMAT=light_core
    #BSM added 20091022
    #export MP_PMDLOG=yes
    export MP_LABELIO=yes
    #BSM end add 20091022
fi

#----------------------------------------------------------------------#
# Decide control file, post workdir and number of atmos domains        #
#----------------------------------------------------------------------#

maxdom=$ATMOS_DOMAINS # number of atmospheric domains
postbase=$CSTREAM/POST/ATMOS_$POST_MODE # where to run the post
delivery=post
if [[ "$OLD_TRACKER" == YES ]]  ; then
    tracker=yes  # yes = make tracker input files
else
    tracker=no   # tracker grib files are made in another job
fi

case "$POST_MODE" in
    NONSAT)  cntrl="$PARMhwrf/hwrf_cntrl.nonsat"      ;;
    SAT)
        delivery="satpost"
        tracker=no

        cntrl_default="$PARMhwrf/hwrf_cntrl.sat_other"
        cntrl="$cntrl_default"
        case "$basin" in
            [Aa][Ll]|[Ll]) cntrl="$PARMhwrf/hwrf_cntrl.satL" ;;
            [Ee][Pp]|[Ee]) cntrl="$PARMhwrf/hwrf_cntrl.satE" ;;
            [Cc][Pp]|[Cc]) cntrl="$PARMhwrf/hwrf_cntrl.satC" ;;
            *)   echo WARNING: UNSUPPORTED BASIN $basin.  
                 echo I ONLY KNOW: AL EP CP
                 echo Using default satellite output options in $cntrl
                 postmsg "$jlogfile" "WARNING: Requested unsupported basin $basin (I only know AL EP and CP).  Using default satellite options in $cntrl"
        esac
        if [[ ! -s "$cntrl" ]] ; then
            echo CONTROL FILE MISSING: $cntrl.  USING DEFAULTS IN $cntrl_default INSTEAD
            cntrl="$cntrl_default"
        fi
        ;;
    BOTH)
        cntrl="$PARMhwrf/hwrf_cntrl.hurcn"

        if [[ "$PARAFLAG" == YES ]] ; then
            postmsg "$jlogfile" "WARNING: POST_MODE is set to BOTH which will fail randomly in about 20% of the cycles due to bugs in the CRTM.  Use POST_MODE of SAT or NONSAT instead."
        else
            die "POST_MODE is set to BOTH which will fail randomly in about 20% of the cycles due to bugs in the CRTM.  Use POST_MODE of SAT or NONSAT instead."
        fi
        ;;
    *)
        die "ERROR: POST_MODE is set to something other than NONSAT, SAT or BOTH.  SCRIPT IS ABORTING."
esac

if [[ ! -s "$cntrl" ]] ; then
    die "ERROR: POST CONTROL FILE $cntrl IS NON-EXISTANT OR EMPTY"
fi

DOMAIN_IN_MASTER=NO # generate domain in post_process instead if NO
if [[ "$DOMAIN_IN_MASTER" == YES ]] ; then
#----------------------------------------------------------------------#
# Generate the post domains
#----------------------------------------------------------------------#
gridfile=$wrfdir/grid_$STORM.$ymdh       # low-res 0.25 degree grid
hr_gridfile=$wrfdir/hr_grid_$STORM.$ymdh # high-res 0.1 degree grid

# Grid is centered at hour 0 outer domain center:
STORMLAT="$cenla"
STORMLON="$cenlo"
if [[ -z "$STORMLAT" || -z "$STORMLON" ]] ; then
    die "STORMLAT=\"$STORMLAT\" and STORMLON=\"$STORMLON\" -- must not be empty"    
fi
echo $STORMLAT  $STORMLON
STORMLON=`echo $STORMLON + 360 | bc` # ensure positive longitudes

# Use 90 latitude degrees by 110 longitude degrees around center:
NORTHB=`echo "$STORMLAT" | awk '{print ($1+45)*1000}'`
SOUTHB=`echo "$STORMLAT" | awk '{print ($1-45)*1000}'`
WESTB=` echo "$STORMLON" | awk '{print ($1+55)*1000}'`
EASTB=` echo "$STORMLON" | awk '{print ($1-55)*1000}'`
echo $NORTHB $SOUTHB $EASTB $WESTB

# Put the post domains in temporary files first since multiple jobs
# may be making the post domain file at the same time, and we don't
# want partial writes
temp_gridfile="$gridfile.$$.$RANDOM.$RANDOM.$RANDOM.$( hostname )"
temp_hr_gridfile="$hr_gridfile.$$.$RANDOM.$RANDOM.$RANDOM.$( hostname )"
echo 255 0 441 361 ${NORTHB} ${EASTB} 136 ${SOUTHB} ${WESTB} 250 250 0 > "$temp_gridfile"
echo 255 0 1101 901 ${NORTHB} ${EASTB} 136 ${SOUTHB} ${WESTB} 100 100 0 > "$temp_hr_gridfile"

# Move the temporary grid files to the new grid files
/bin/mv -f "$temp_gridfile" "$gridfile"
/bin/mv -f "$temp_hr_gridfile" "$hr_gridfile"

echo "POST LOW-RES DOMAIN:  $( cat $gridfile )"
echo "POST HIGH_RES DOMAIN: $( cat $hr_gridfile )"
fi
#----------------------------------------------------------------------#
# Utility functions                                                    #
#----------------------------------------------------------------------#

function now {
   date +%s
}

function postit {
    # This function posts one output time, specified by forecast hour $ihour,
    # with input files $outfiles, using working directory $postdir.

    set -x

    # Go to the post directory:
    cd "$postdir"
    if [[ "$?" != 0 ]] ; then
        die "Unable to cd to $postdir"
    fi

    # List the files we will be posting:
    echo "$outfiles" > wrfout.lst

    # Run the post, subset via copygb and wgrib:
    "$USHhwrf/hwrf_post_process.sh" $more_opts "$STORM" "$STORMID" "$YYYYMMDDHH" "$cntrl" "$cenla" "$cenlo" $outfiles

    # Copy files to destination locations:
    "$USHhwrf/hwrf_post_deliver.sh" "$delivery" "$STORM" "$STORMID" "$wrfdir" "$YYYYMMDDHH" "$ihour" "$COMOUT" "$maxdom"

    # Signify success to parent process:
    return 0
}

function cycle_file {
    # This script appends many tracker input grib files to make one big
    # file with all output times.

    set -x

    # Arguments:
    where="$1"  # subdirectory of $wrfout in which to operate
    what="$2"   # portion of input file names after $ymdh.
    how="$3"    # portion of output filenames after grbf-cycle.

    dir=$wrfdir/$where
    out=$dir/hwrf.t${CYC}z.grbf-cycle.$how

    # We will first produce a temporary file $temp:
    temp=$out.TEMP.$RANDOM.$RANDOM.$RANDOM
    rm -f "$temp"

    # Loop over all forecast times.  
    # ALL forecast times, not just the ones we have processed so far.
    for jhour in $( seq 0 3 126 ) ; do

        # Figure out what file we're appending:
        file=$( printf %s%02d "$dir/$STORM$STORMID.$ymdh.$what" $jhour )

        if [[ ! -s "$file" ]] ; then
            if [[ "$jhour" -gt "$ihour" ]] ; then
                # The file does not exist, and is after the last hour
                # we've posted, so we can make the final output file now:
                break;
            fi

            # If we get here, the file does not exist, but is a file
            # we've already post-processed, then this is an error.

            # We call hwrf_file_complete.pl here to wait for the file
            # to exist.  That is just a placeholder for future
            # multi-job post-processing.
            if ( ! $USHhwrf/hwrf_file_complete.pl -s 1 -o 5 -w 30 $file ) ; then
                die "Tracker input file $file does not exist or is empty.  Post failed."
            fi
        fi

        # This input file $file exists, so we can append it to $tmp:
        $wgrib -s $file |grep NAve |$wgrib -i -grib -append $file -o $temp
    done

    # The $temp temporary file contains all available forecast hours.
    # Move it to the destination file $out
    /bin/mv -f "$temp" "$out"
}

#----------------------------------------------------------------------#
# Wait for wrf output directory to be created                          #
#----------------------------------------------------------------------#

avalable=no
start=$( now )
giveup=$(( start + 2700 )) # wait up to 2700 seconds (45 min)
while [[ $( now ) -lt "$giveup" ]] ; do
    # Wait until the output directory exists
    if ( $USHhwrf/hwrf_file_complete.pl -w60 -S10 -o0 -d "$wrfdir" ) ; then
        echo OUTPUT DIR $wrfdir IS AVAILABLE
        available=yes
        break
    fi
    if [[ "$PARAFLAG" == YES ]] ; then
        $USHhwrf/hwrf_port_checksig.sh
    fi
done

if [[ "$available" != yes ]] ; then
    die "$wrfdir is not created.  Check if model is running fine."
fi

#----------------------------------------------------------------------#
# Post all output times                                                #
#----------------------------------------------------------------------#
if [[ "$PARAFLAG" == YES ]] ; then
    $USHhwrf/hwrf_port_checksig.sh
fi

for ihour in $( seq $firsthour $increment $lasthour ) ; do
    echo $ihour
    
    if [[ "$delivery" == post  &&  $ihour == 0   ]] ; then
        echo This is the first post-processing hour, so I will delete all
        echo tracker input files.
        rm -rf $wrfdir/PARENT $wrfdir/NEST $wrfdir/COMBINE $wrfdir/DOM12
        mkdir $wrfdir/PARENT
        mkdir $wrfdir/NEST
        mkdir $wrfdir/COMBINE
        if [[ "$maxdom" -ge 3 ]] ; then
            mkdir $wrfdir/DOM12
        fi
    fi
    
  todo=2

  # Create a unique $postdir directory name for this forecast hour.
  # This is done as a placeholder for future multi-job post-processing.
  postdir=$postbase/$( printf %s%02d F $ihour )

  # Delete and recreate the post-processing directory:

  rm -rf "$postdir"
  if [[ -e "$postdir" || -L "$postdir" ]] ; then
      echo WARNING: cannot delete $postdir
  fi
  $USHhwrf/hwrf_mkdirp.sh "$postdir"
  if [[ ! -d "$postdir" ]] ; then
      die "ERROR: Unable to create directory $postdir"
  fi

  # We need to run a post-processor on this output time.

  # Generate the date string for this forecast time:

  VDATE=`$ndate $ihour $ymdh`
  YYYY=`echo $VDATE |cut -c1-4`
  MMMM=`echo $VDATE |cut -c5-6`
  DDDD=`echo $VDATE |cut -c7-8`
  HHHH=`echo $VDATE |cut -c9-10`
  VERIF_DATE=$YYYY-$MMMM-$DDDD"_"$HHHH:00:00
  echo $VERIF_DATE
  
  # Decide the wrfout file names, up to the current hour:

  outfile_d01=$wrfdir/wrfout_d01_$VERIF_DATE
  if [[ "$maxdom" -gt 1 ]] ; then
      outfile_d02=$wrfdir/wrfout_d02_$VERIF_DATE
      if [[ "$maxdom" -gt 2 ]] ; then
          outfile_d03=$wrfdir/wrfout_d03_$VERIF_DATE
      fi
  fi
  outfiles="$outfile_d01 $outfile_d02 $outfile_d03"
  
  # Wait for all wrfout files for this time to be written out:

  avalable=no
  start=$( now )
  giveup=$(( start + 3600 )) # wait up to 3600 sec (1 hr)
  while [[ $( now ) -lt "$giveup" ]] ; do
      # Wait until all wrfout files for this time are available:
      if ( $USHhwrf/hwrf_file_complete.pl -s 10485760 -o $minage -w 60 $outfiles ) ; then
          echo FILES ARE AVAILABLE AT FORECAST HOUR $ihour
          available=yes
          break
      fi
      if [[ "$PARAFLAG" == YES ]] ; then
          $USHhwrf/hwrf_port_checksig.sh
      fi
  done
  
  if [[ "$available" != yes ]] ; then
      die 'There is a problem with the model run, wrfout files are not created' \
          "for time $VERIF_DATE.  Check if the model is running fine, now exiting."
  fi

# Post this output time:
  
  if [[ "$PARAFLAG" == YES ]] ; then
      $USHhwrf/hwrf_port_checksig.sh
  fi
  if ( ! time postit ) ; then
      die "ABORTING: Non-zero exit status from postit.  This should not be possible -- postit should have called err_exit instead.  Maybe err_exit is taking a while to abort?"
  fi
  if [[ "$PARAFLAG" == YES ]] ; then
      $USHhwrf/hwrf_port_checksig.sh
  fi

# rm -rf "$postdir"
# if [[ -e "$postdir" || -L "$postdir" ]] ; then
#     postmsg "$jlogfile" "WARNING: cannot delete $postdir"
# fi
  if [[ "$PARAFLAG" == YES ]] ; then
      $USHhwrf/hwrf_port_checksig.sh
  fi

  if [[ "$tracker" == yes ]] ; then
      if [[ "$ihour" == 12 || "$ihour" == 126 ]] ; then
          # Time to make tracker input files.
          cycle_file PARENT parent_grbf parent
          if [[ "$PARAFLAG" == YES ]] ; then
              $USHhwrf/hwrf_port_checksig.sh
          fi
          cycle_file NEST nest_grbf nest
          if [[ "$PARAFLAG" == YES ]] ; then
              $USHhwrf/hwrf_port_checksig.sh
          fi
          cycle_file COMBINE combine_grbf combined
          if [[ "$PARAFLAG" == YES ]] ; then
              $USHhwrf/hwrf_port_checksig.sh
          fi
          if [[ "$maxdom" -ge 3 ]] ; then
              cycle_file DOM12 combine12_grbf dom12
              if [[ "$PARAFLAG" == YES ]] ; then
                  $USHhwrf/hwrf_port_checksig.sh
              fi
          fi
      fi
  fi
done

