#!/bin/bash
set -e
#
# cccjob template for a diagnostics only job string on PPP2
#
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
# config file
canesm_cfg_file=canesm.cfg
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#

# Source the config file
. ${canesm_cfg_file}

# derive start_year and start_month
start_list=(${start_time//:/ })
start_year=${start_list[0]:-1}
start_month=${start_list[1]:-1}

# derive stop_year and stop_month
stop_list=(${stop_time//:/ })
stop_year=${stop_list[0]:-1}
stop_month=${stop_list[1]:-12}

# derive run_start_year and run_start_month
run_start_list=(${run_start_time//:/ })
run_start_year=${run_start_list[0]:-1}
run_start_month=${run_start_list[1]:-1}

# derive year_rtdiag_start and month_rtdiag_start
start_rtdiag_time=(${start_rtdiag//:/ })
year_rtdiag_start=${start_rtdiag_time[0]:-1}
month_rtdiag_start=${start_rtdiag_time[1]:-1}

# Change any or all of the following as required

# start and stop control the length of this job string
# They are both of the form year:month or just year, where year and month are positive integers
# With the year:month format, at least one of year or month must be defined.
#   -if month is missing then it will default to 1 for start and 12 for stop
#   -if year is missing then it will default to 1 for start and start_year for stop
# With the year only format, start month will be 1 and stop month will be 12
start=2003
stop=2003

#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
#=#=# BEGIN preamble...do not modify
# Internal definitions
Runame=$(basename $0)
# Error exit with message (executed as a simple command)
bail(){
  echo $(date)" --- *EE* ${Runame}: $*"
  exit 1
}
# Issue a warning but do not exit
warn(){
  echo $(date)" --- *WW* ${Runame}: $*"
}
# Emit an informational message
info(){
  echo $(date)" --- *II* ${Runame}: $*"
}
# A pattern to match a string of the form INT:INT (INT a positive integer or zero)
patt1='^[0-9][0-9]*:[0-9][0-9]*$'
# A pattern to match a single positive integer or zero
patt2='^[0-9][0-9]*$'
# Process start or stop parameters (both will contain year:month values)
process_date_param(){
  local pnam pval pyear pmon dyear dmon
  local -a Aval
  # Process a date parameter (currently only start or stop are recognized)
  [ -z "$1" ] && bail "${FUNCNAME[0]} $*
 *EE* ${FUNCNAME[0]} requires a variable name on the command line whose value is of the form year:month, or just year"
  # Verify that the parameter name is valid and set a default year and month
  # for each name specified, to be used when the year or month info is missing.
  # Note that the default stop year depends on the start year and so the start
  # parameter should be processed before the stop parameter.
  case $1 in
    start) dyear=1; dmon=1  ;;             # Expected parameter name
     stop) dyear=${start_year:-1}; dmon=12 # Expected parameter name
           # If start_year is not defined then let the user know
           [ -z "$start_year" ] &&
           info "${FUNCNAME[0]}:
 *II* ${FUNCNAME[0]}: Normally stop is defined after start is defined.
 *II* ${FUNCNAME[0]}: You are currently defining stop before start is defined.
 *II* ${FUNCNAME[0]}: Setting default stop year to $dyear"
           ;;
    *) bail "${FUNCNAME[0]}: Invalid parameter name -->$1<--" ;;
  esac
  pnam=$1
  eval pval=\$$1
  [ -z "$pval" ] && bail "${FUNCNAME[0]}: $pnam must be defined and not null"
  local msg_comm="$pnam should be of the form year:month, or just year, where month and year are positive integers."

  if [[ $pval =~ ":" ]]; then
    # Split on colon
    Aval=(${pval//:/ })
    if [ ${#Aval[*]} == 0 ]; then
      # The array is empty (ie just a single colon in pval)
      bail "${FUNCNAME[0]}: Invalid value for ${pnam}=$pval missing year and month $msg_comm"
    elif [ ${#Aval[*]} == 1 ]; then
      # Only 1 element in Aval, meaning the single colon is either the first or last character
      if [[ ${pval:0:1} = ":" ]]; then
        # The colon is the first character (year is missing and month is present)
        # Assume the default, that is set above, for year
        pyear=$dyear
        pmon=${Aval[0]}
        warn "${FUNCNAME[0]}: $pnam is missing a value for year. $msg_comm Using $pnam year=$pyear $pnam month=$pmon"
      else
        # The colon is the last character (year is present but month is missing)
        # Assume the default, that is set above, for month
        pyear=${Aval[0]}
        pmon=$dmon
        warn "${FUNCNAME[0]}: $pnam is missing a value for month. $msg_comm Using $pnam year=$pyear $pnam month=$pmon"
      fi
    else
      # At least 2 elements in Aval
      pyear=${Aval[0]:-$dyear}
      pmon=${Aval[1]:-$dmon}
    fi
  elif [[ $pval =~ $patt2 ]]; then
    # The parameter value is a positive integer or zero
    # Assume it is the year and set month to the default value defined above
    pyear=$pval
    pmon=$dmon
    # warn "${FUNCNAME[0]}: ${pnam}=$pval is a single integer. Using $pnam year=$pyear $pnam month=$pmon"
  else
    bail "${FUNCNAME[0]}: Invalid value for ${pnam}=$pval  ...$msg_comm"
  fi
  # At this point the local variables pyear and pmon should be defined with
  # values consistent with the value of the user supplied parameter name.
  # Verify that pyear and pmon are integers with reasonable values
  [[ $pyear =~ $patt2 ]] ||
      bail "Invalid ${pnam}=$pval ...The year is not a positive integer or zero. $msg_comm"
  [[ $pyear < 0 ]] &&
      bail "Invalid ${pnam}=$pval ...The year is less that zero. $msg_comm"
  [[ $pmon  =~ $patt2 ]] ||
      bail "Invalid ${pnam}=$pval ...The month is not a positive integer. $msg_comm"
  [ $pmon -lt 1 -o $pmon -gt 12 ]  &&
    bail "Invalid ${pnam}=${pval} ...month=$pmon is out of range. $msg_comm"

  # Format local year and month values
  pyear=`echo $pyear | awk '{printf "%d",$1}'`
  pmon=`echo $pmon | awk '{printf "%02d",$1}'`

  # Define global variables ${pnam}_year, ${pnam}_mon and ${pnam}_time for use elsewhere
  eval ${pnam}_year=$pyear
  eval ${pnam}_mon=$pmon
  Aval[0]=$pyear
  Aval[1]=$pmon
  eval ${pnam}_time=\(${Aval[@]}\)
  eval echo \"${FUNCNAME[0]}: ${pnam}_year=\$pyear  ${pnam}_mon=\$pmon\"
}
#=#=# END preamble
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#

# Create variables start_year, start_mon and start_time using info in start
# start should be processed before stop so that reasonable defaults can be used for stop
process_date_param start
echo start_year=$start_year start_mon=$start_mon

# Create variables stop_year, stop_mon and stop_time using info in stop
process_date_param stop
echo stop_year=$stop_year stop_mon=$stop_mon

# The chunk_size in months (must correspond to an integer number of years)
chunk_size=`echo $start_year $start_mon $stop_year $stop_mon | awk '{printf "%d",($3-$1)*12+($4-$2)+1}'`
if [ $chunk_size -gt 12 ] ; then
  chunk_size=12
fi
echo chunk_size=$chunk_size

# months for GCM and restart files
last_month=`expr $start_mon + 11` # last month in a year
end_month=`expr $start_mon + $months_run - 1` # last month in $months_run chunk
exe_month=`expr $start_mon + $months - 1` # last month in $months chunk
months_gs="+`seq $start_mon $months_run $last_month | awk '{print ($1-1)%12+1}'|tr '\n' ','`"
months_rs="+`seq $end_month $months_run $last_month | awk '{print ($1-1)%12+1}'|tr '\n' ','`"
months_ab="+`seq $exe_month $months     $last_month | awk '{print ($1-1)%12+1}'|tr '\n' ','`"

echo months_run=$months_run
echo months_gs=$months_gs
echo months_rs=$months_rs
echo months_ab=$months_ab

# Year of the restart files for the first year
if [ $start_mon -eq 1 ] ;then
  start_year_rs=`expr $start_year - 1`
  start_mon_rs=12
else
  start_year_rs=$start_year
  start_mon_rs=`echo $start_mon | awk '{printf "%02d",$1-1}'`
fi
echo start_year_rs=$start_year_rs start_mon_rs=$start_mon_rs

# months=1 would normally be used here ...but it can be reset if required for special cases
months=1
months_gcm=$months_run # keep months_run value as months_gcm (needed for gcmpak.dk)
months_run=1 # reset months_run to 1

#==========================================================================================
# Variables coming in from ${canesm_cfg_file}, modified here
#==========================================================================================

canesm_dump_hist_suffix_list=`echo $canesm_dump_hist_suffix_list | sed "s/+months_rs/${months_rs}/g;s/+months_gs/${months_gs}/g;s/+months_ab/${months_ab}/g"`
canesm_dump_histRS0_suffix_list=`echo $canesm_dump_histRS0_suffix_list | sed "s/+months_rs/+${start_mon_rs}/g;s/+months_gs/+${start_mon_rs}/g;s/+months_ab/+${start_mon_rs}/g"`
canesm_dump_histRS_suffix_list=`echo $canesm_dump_histRS_suffix_list | sed "s/+months_rs/${months_rs}/g;s/+months_gs/${months_gs}/g;s/+months_ab/${months_ab}/g"`

# The job created here uses the second character from uxxx to determine the type of
# pooling and/or the prefix for diagnostic and time series files
# Verify that uxxx contains a reasonable value
[ -z "$uxxx" ] && bail "uxxx must be defined"
ch2=$(echo $uxxx|awk '{print substr($1,2,1)}' -)
[ -z "$ch2" ] && bail "Invalid uxxx = $uxxx"
case $ch2 in
  a|m|c|r|d|f) ;; # These are valid
  *) bail "Invalid prefix found in uxxx = $uxxx" ;;
esac

stamp=`date "+%j%H%M%S"$$`
diagjob_sfx=dumpjob_`echo ${CMCFEDEST} | cut -f2 -d'-'`_$stamp
jobdefs=jobdefs_dumpjob_$stamp
cat >> $jobdefs << end_jobdefs
  uxxx=$uxxx
  runid=$runid
  months=$months
  months_run=$months_run
  months_gcm=$months_gcm
  chunk_size=$chunk_size
  noprint=$noprint
  debug=$debug
  crawork=${runid}_${diagjob_sfx}

  # Archive short term switch
  canesm_dump_hist_short_term=$canesm_dump_hist_short_term
  canesm_dump_histRS_short_term=$canesm_dump_histRS_short_term
  canesm_dump_histRS0_short_term=$canesm_dump_histRS_short_term
  canesm_dump_diag_short_term=$canesm_dump_diag_short_term
  canesm_dump_tser_short_term=$canesm_dump_tser_short_term
  canesm_dump_nc_short_term=$canesm_dump_nc_short_term

  # Archive checksum switch
  hpcarchive_checksum=$hpcarchive_checksum

  # This is a list of history files which will get dumped from sitestore to tape using hpcarchive. Files must exist.
  canesm_dump_hist_prefix="${canesm_dump_hist_prefix}"
  canesm_dump_hist_suffix_list="${canesm_dump_hist_suffix_list}"

  # This is a list of restart files before the very 1st year.
  canesm_dump_histRS0_prefix="${canesm_dump_histRS0_prefix}"
  canesm_dump_histRS0_suffix_list="${canesm_dump_histRS0_suffix_list}"

  # This is a list of restart files which will get dumped from sitestore to tape using hpcarchive. Files must exist.
  canesm_dump_histRS_prefix="${canesm_dump_histRS_prefix}"
  canesm_dump_histRS_suffix_list="${canesm_dump_histRS_suffix_list}"

  # This is a list of files which will get dumped from sitestore to tape using hpcarchive. Files must exist.
  canesm_dump_diag_suffix_list="${canesm_dump_diag_suffix_list}"

  # mdeleteHIST_suffix_list indicates the model history file suffixes to remove on frontend after diagnostics are done
  mdeleteHIST_suffix_list="${mdeleteHIST_suffix_list}"
  mdeleteHIST_bexfer="${mdeleteHIST_bexfer}" # =off to delete files on frontend, =on to delete files on backend
  mdeleteHIST_leave_last_mon="${mdeleteHIST_leave_last_mon}" # =off to delete full year, =on to leave last month from previous year

  # mdeleteRS_suffix_list indicates the restart file suffixes to remove on frontend after diagnostics are done
  mdeleteRS_suffix_list="${mdeleteRS_suffix_list}"
  mdeleteRS_bexfer="${mdeleteRS_bexfer}" # =off to delete files on frontend, =on to delete files on backend
  mdeleteRS_leave_last_mon="${mdeleteRS_leave_last_mon}" # =off to delete full year, =on to leave last month from previous year

  # mdelete_suffix_list indicates the model file suffixes to remove on frontend after diagnostics are done
  mdeleteDIAG_prefix_list="${mdeleteDIAG_prefix_list}"
  mdeleteDIAG_suffix_list="${mdeleteDIAG_suffix_list}"
  mdeleteDIAG_leave_last_mon="${mdeleteDIAG_leave_last_mon}" # =off to delete full year, =on to leave last month from previous year

  # netcdf parameters
  with_dump_nc=${with_dump_nc}
  with_del_nc=${with_del_nc}
  keep_vartab_pairs=${keep_vartab_pairs}
end_jobdefs

# Define the name of the file to contain the output job string
date1=`echo ${start_time[0]:-1} ${start_time[1]:-1} | awk '{printf "%3.3dm%2.2d",$1,$2}'`
date2=`echo ${stop_time[0]:-1} ${stop_time[1]:-12} | awk '{printf "%3.3dm%2.2d",$1,$2}'`
if [[ ${#start_time[@]} -gt 2 ]]; then
  [ -n "${start_time[2]}" ] && printf -v d1 "d%2.2d" ${start_time[2]} && date1+="$d1"
fi
if [[ ${#stop_time[@]} -gt 2 ]]; then
  [ -n  "${stop_time[2]}" ] && printf -v d2 "d%2.2d" ${stop_time[2]}  && date2+="$d2"
fi

# Dump restart files to tape
if [ $with_dump_rs -eq 1 ]; then
  if [ $start_year -eq $run_start_year -a $start_mon -eq $run_start_month ] ; then
    # dump additional files before the very 1st year
    DUMPRS="canesm_dump_histRS0:n canesm_dump_histRS:1m"
  else
    DUMPRS="canesm_dump_histRS:1m"
  fi
else
  DUMPRS=''
fi

# Dump history files to tape
if [ $with_dump_hist -eq 1 ]; then
  DUMPHIST="canesm_dump_hist:1m"
else
  DUMPHIST=''
fi

# Dump diagnostic files to tape
if [ $with_dump_diag -eq 1 ]; then
  DUMPDIAG="canesm_dump_diag:${chunk_size}m"
else
  DUMPDIAG=''
fi

# Dump time series files to tape
if [ $with_dump_tser -eq 1 ]; then
  DUMPTSER="canesm_dump_tser:${chunk_size}m"
else
  DUMPTSER=''
fi

# Delete history files on ppp after diagnostics are done
if [ $with_delhistFE -eq 1 ]; then
  DELHISTFE="mdeleteHIST:${chunk_size}m"
else
  DELHISTFE=''
fi

# Delete restart files on ppp after diagnostics are done
if [ $with_delrsFE -eq 1 ]; then
  DELRSFE="mdeleteRS:${chunk_size}m"
else
  DELRSFE=''
fi

# Delete diagnostic files on ppp after dumping is done
if [ $with_deldiag -eq 1 ]; then
  DELDIAG="mdeleteDIAG:${chunk_size}m"
else
  DELDIAG=''
fi

# Delete time series files to tape
if [ $with_del_tser -eq 1 ]; then
  DELTSER="canesm_delete_tser:${chunk_size}m"
else
  DELTSER=''
fi

# Archive/Delete netcdf files
if [ $with_dump_nc -eq 1 ] || [ $with_del_nc -eq 1 ] ; then
  DUMPDELNC="canesm_dumpdel_netcdf:12m"
else
  DUMPDELNC=''
fi

# Run code checking and update logs
[ $production -eq 1 ] && flgs="" || flgs="-d"   # use 'development' mode if production is off
strict_check $flgs $runid create-dump-job-string-${date1}_${date2} canesm.cfg make_dump_job_${runid}
[ $? -ne 0 ] && exit 1

# Job description
JOBDESC="$DUMPRS $DELRSFE $DUMPHIST $DELHISTFE $DUMPDIAG $DELDIAG $DUMPTSER $DELTSER $DUMPDELNC"
echo JOBDESC=$JOBDESC

# Create the complete job string
range="${date1}_${date2}"
fout="${runid}_${range}_dump_job"
if [ ! -z "${JOBDESC// }" ] ; then
  cccjob --out=$fout --job="$JOBDESC" --start=$start --stop=$stop $jobdefs
fi
rm -f $jobdefs
