#!/bin/bash
#
# Note: (system) returns
#       222, reserved by timeout.
#       223, if we failed in retreiving NWP data.
#       224, qc fails critical - which should be debugged.
#       225, if bgf file is missing, but dis is there - this should be debugged.
#       238, missing/bad input arguments.
#
[ -f ./gpac_env_vars.sh ] || { echo "Environment file './gpac_env_vars.sh' does not exist"; exit 238; }

# set -o verbose
. ./gpac_env_vars.sh


occ_abs_path=${GPAC_WRKDIR}/occ_${GPAC_PID}.nc
ben_abs_path=${GPAC_WRKDIR}/ben_${GPAC_PID}.nc
bet_abs_path=${GPAC_WRKDIR}/bet_${GPAC_PID}.nc
atm_abs_path=${GPAC_WRKDIR}/atm_${GPAC_PID}.nc
wet_abs_path=${GPAC_WRKDIR}/wet_${GPAC_PID}.nc
wfm_abs_path=${GPAC_WRKDIR}/wfm_${GPAC_PID}.nc
bgo_abs_path=${GPAC_WRKDIR}/bgo_${GPAC_PID}.nc
bgn_abs_path=${GPAC_WRKDIR}/bgn_${GPAC_PID}.nc
bgf_abs_path=${GPAC_WRKDIR}/bgf_${GPAC_PID}.nc
bga_abs_path=${GPAC_WRKDIR}/bga_${GPAC_PID}.nc
bgr_abs_path=${GPAC_WRKDIR}/bgr_${GPAC_PID}.nc  # temporary file
bge_abs_path=${GPAC_WRKDIR}/bge_${GPAC_PID}.nc
dfm_abs_path=${GPAC_WRKDIR}/dfm_${GPAC_PID}.nc  # temporary file
cor_abs_path=${GPAC_WRKDIR}/cor_${GPAC_PID}.nc
att_abs_path=${GPAC_WRKDIR}/att_${GPAC_PID}.nc  # temporary file
ate_abs_path=${GPAC_WRKDIR}/ate_${GPAC_PID}.nc
cvs_abs_path=${GPAC_WRKDIR}/cvs_${GPAC_PID}.nc
grh_abs_path=${GPAC_WRKDIR}/grh_${GPAC_PID}.nc
tph_abs_path=${GPAC_WRKDIR}/tph_${GPAC_PID}.nc  # temporary file
dis_abs_path=${GPAC_WRKDIR}/dis_${GPAC_PID}.nc
bfr_abs_path=${GPAC_WRKDIR}/bfr_${GPAC_PID}.bin
pnc_abs_path=${GPAC_WRKDIR}/pnc_${GPAC_PID}.nc
ppc_abs_path=${GPAC_WRKDIR}/ppc_${GPAC_PID}.nc
qcr_abs_path=${GPAC_WRKDIR}/qcr_${GPAC_PID}.json  # perhaps specify this in gpac_env_vars.sh
nwp_retriever_settings_ei=${NWP_RETRIEVER_SETTINGS_EI}
nwp_retriever_settings_od=${NWP_RETRIEVER_SETTINGS_OD}
qcr_settings=${QCR_SETTINGS}
# set +o verbose

#
# Wrapper (to print version number and handle error).
#
cmd_wrapper() {
    echo ""
    echo "+++ Running: $*"
    # Get version
    echo "$(eval $1 -v)"
    # Run command
    eval $*
    status=$?
    if [ $status -ne 0 ]; then
        echo "$1 failed, status: $status"
    fi
    return $status
}


#--- 1. Convert input file formats
if [ -f "${GPAC_ATMPHS_ABS_PATH}" ]; then
    # ATMPHS file from ucar.
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ucar2ropp \
        ${GPAC_ATMPHS_ABS_PATH} \
        -o ${occ_abs_path} \
        -u \
        -d \
        --no-ranchk
elif [ -f "${GPAC_NC4_ABS_PATH}" ]; then 
    # NC4 file from eumetsat.
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/eum2ropp \
        ${GPAC_NC4_ABS_PATH} \
        -o ${bet_abs_path} \
        -r thinned \
        -e \
        -u \
        -d \
        --no-ranchk
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/eum2ropp \
        ${GPAC_NC4_ABS_PATH} \
        -o ${ben_abs_path} \
        -r high_resolution \
        -e \
        -u \
        -d \
        --no-ranchk
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/eum2ropp \
        ${GPAC_NC4_ABS_PATH} \
        -o ${occ_abs_path} \
        -x \
        -l cl+ol \
        -c \
        -u \
        -d \
        --no-ranchk
else
    echo "No valid input file are defined"
    exit 238
fi

# If occ file is not produced - no need to continue, just exit!
[ -f ${occ_abs_path} ] || { echo "***ERROR: occ file not produced!"; exit 1; }

#--- 2. Process to bangle, refrac, and dry temp

#----2.1 Generate observation profiles
if [ -f "${GPAC_GPSBIT_ABS_PATH}" ]; then
    navopt="-navfile ${GPAC_GPSBIT_ABS_PATH}"
else
    navopt=""
fi
if [ ! -f "${GPAC_ATTRIBUTE_CFG}" ]; then
    GPAC_ATTRIBUTE_CFG=$(trn_attributes_path ${occ_abs_path})
fi
cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_pp_occ_tool ${occ_abs_path} \
    -o ${atm_abs_path} \
    -c ${GPAC_MISSION_CFG} \
    -a ${GPAC_ATTRIBUTE_CFG} \
    ${navopt} \
    -egm96 ${GEOPOT_COEF} \
    -cegm96 ${GEOPOT_CORR} \
    -mfile ${GPAC_ROPP_ROOT}/data/BAROCLIM_coeff.nc \
    -msisfile ${GPAC_ROPP_ROOT}/data/MSIS_coeff.nc \
    -d \
    ${OPTATM} \
    --no-ranchk

status=$?

# If atm file is not produced or processing error - no need to continue, just exit!
# Continue on processing warning.
if [ ! -f ${atm_abs_path} ] || [ $status -ne 0 ]; then
    if [ ! -f ${atm_abs_path} ] || [ $status -ne 1 ]; then
        echo "***ERROR: atm file not produced / bad return code! Setting file(s) to non nominal"
        gpac_qc set ${occ_abs_path} ${atm_abs_path} --pcd 113 --or
        exit 2
    fi
    echo "***WARNING: return code = 1! Continuing."
fi

# set status to OK, for now
declare -i overall_status
overall_status=0

#--- 2.2 Thinning of observed refractivity: atm -> att
#        Also removes Vlist
cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp2ropp ${atm_abs_path} \
    -p ${GPAC_ROPP_ROOT}/data/ropp_thin_eum-247.dat \
    -o ${att_abs_path} \
    -b ${GPAC_ATTRIBUTE_CFG} \
    -s \
    --no-ranchk

#--- 2.3 Tropopause height and tropopause parameters


cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_apps_tph_tool ${atm_abs_path} \
    -o ${tph_abs_path} \
    -a ${GPAC_ATTRIBUTE_CFG} \
    -b \
    -n \
    -y \
    --no-ranchk

# Move tph file to atm file, if it has been produced.
if [ -f ${tph_abs_path} ]; then
    mv ${tph_abs_path} ${atm_abs_path}
else
    echo "***ERROR: ${tph_abs_path} not produced."
    overall_status=3
fi


#--- 3. Generate background profiles

#--- 3.1 Find the GRIB files by reading info from atm files. 
#        Returns a string with the grib file path(s), lat, and lon.
echo "Get EI GRIB files, based on atm file ..."
GRIB_FILE_STR=$(time get_nwp ${nwp_retriever_settings_ei} ${atm_abs_path})
status=$?
[ $status -eq 0 ] || { echo "***ERROR, get_nwp failed, status $status"; exit 223; }

#--- 3.2 Dissect the string.
FC_FILE_LEFT=$(echo $GRIB_FILE_STR | cut -d' ' -f 1)
FC_FILE_RIGHT=$(echo $GRIB_FILE_STR | cut -d' ' -f 2)
AN_FC_FILE_LEFT=$(echo $GRIB_FILE_STR | cut -d' ' -f 3)
AN_FC_FILE_RIGHT=$(echo $GRIB_FILE_STR | cut -d' ' -f 4)
AN_FILE_LEFT=$(echo $GRIB_FILE_STR | cut -d' ' -f 5)
AN_FILE_RIGHT=$(echo $GRIB_FILE_STR | cut -d' ' -f 6)
LAT=$(echo $GRIB_FILE_STR | cut -d' ' -f 7)
LON=$(echo $GRIB_FILE_STR | cut -d' ' -f 8)

#--- 3.3 Diagnostics.
echo "USING EI FORECAST GRIB FILES : $FC_FILE_LEFT $FC_FILE_RIGHT" 
echo "USING EI OROGRAPHY FROM : $AN_FC_FILE_LEFT"  
echo "USING EI ANALYSIS GRIB FILES : $AN_FILE_LEFT $AN_FILE_RIGHT" 
echo "POSITION: LAT: $LAT LON $LON"

#--- 3.4 Extract two background profiles from GRIB files: bgf and bga
cmd_wrapper ${GPAC_ROPP_ROOT}/bin/grib2bgrasc $FC_FILE_LEFT \
    -g $FC_FILE_RIGHT \
    -z $AN_FC_FILE_LEFT \
    -y ${atm_abs_path} \
    -x ${bgf_abs_path} \
    --no-ranchk

cmd_wrapper ${GPAC_ROPP_ROOT}/bin/grib2bgrasc $AN_FILE_LEFT \
    -g $AN_FILE_RIGHT \
    -y ${atm_abs_path} \
    -x ${bga_abs_path} \
    --no-ranchk

if [ ! -f ${bga_abs_path} ]; then
    echo "***ERROR: bga file not produced!"
    overall_status=4
fi

#--- 3.5 Get OD nwp file

echo "Get OD GRIB files, based on atm file ..."
GRIB_FILE_STR=$(time get_nwp ${nwp_retriever_settings_od} ${atm_abs_path})
status=$?
[ $status -eq 0 ] || { echo "***ERROR, get_nwp failed, status $status"; exit 223; }
#--- 3.xx Dissect the string.
FC_FILE_LEFT=$(echo $GRIB_FILE_STR | cut -d' ' -f 1)
AN_FC_FILE_LEFT=$(echo $GRIB_FILE_STR | cut -d' ' -f 2)
AN_FILE_LEFT=$(echo $GRIB_FILE_STR | cut -d' ' -f 3)
LAT=$(echo $GRIB_FILE_STR | cut -d' ' -f 4)
LON=$(echo $GRIB_FILE_STR | cut -d' ' -f 5)

#--- 3.6 Diagnostics.
echo "USING OD FORECAST GRIB FILE : $FC_FILE_LEFT" 
echo "USING OD OROGRAPHY FROM : $AN_FC_FILE_LEFT"  
echo "USING OD ANALYSIS GRIB FILE : $AN_FILE_LEFT" 
echo "POSITION: LAT: $LAT LON $LON"

#--- 3.7 Extract background profiles from GRIB files: bgo and bgn

cmd_wrapper ${GPAC_ROPP_ROOT}/bin/grib2bgrasc $FC_FILE_LEFT \
     -z $AN_FC_FILE_LEFT \
     -y ${atm_abs_path} \
     -x ${bgo_abs_path} \
     --no-ranchk

cmd_wrapper ${GPAC_ROPP_ROOT}/bin/grib2bgrasc $AN_FILE_LEFT \
     -y ${atm_abs_path} \
     -x ${bgn_abs_path} \
     --no-ranchk

if [ ! -f ${bgn_abs_path} ]; then
    echo "***ERROR: bgn file not produced!"
    overall_status=5
fi

#--- 3.8 Forward model to bangle, refrac, and dry temp 
cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_fm_bg2ro_1d ${bgf_abs_path} \
    -o ${dfm_abs_path} \
    -a ${GPAC_ROPP_ROOT}/etc/nwp_ei_fc_attrb.cf \
    -l ${atm_abs_path} \
    -f \
    -d \
    -new_op \
    -comp \
    --no-ranchk

if [ -f ${dfm_abs_path} ]; then
    mv ${dfm_abs_path} ${bgf_abs_path}
else
    echo "***ERROR: ${dfm_abs_path} does not exist!"
    overall_status=7
fi

cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_fm_bg2ro_1d ${bga_abs_path} \
    -o ${dfm_abs_path} \
    -a ${GPAC_ROPP_ROOT}/etc/nwp_ei_an_attrb.cf \
    -l ${atm_abs_path} \
    -f \
    -d \
    -new_op \
    -comp \
    --no-ranchk

if [ -f ${dfm_abs_path} ]; then
    mv ${dfm_abs_path} ${bga_abs_path}
else
    echo "***ERROR: ${dfm_abs_path} does not exist!"
    overall_status=8
fi

cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_fm_bg2ro_1d ${bgo_abs_path} \
    -o ${dfm_abs_path} \
    -a ${GPAC_ROPP_ROOT}/etc/nwp_od_fc_attrb.cf \
    -l ${atm_abs_path} \
    -f \
    -d \
    -new_op \
    -comp \
    --no-ranchk

if [ -f ${dfm_abs_path} ]; then
    mv ${dfm_abs_path} ${bgo_abs_path}
else
    echo "***ERROR: ${dfm_abs_path} does not exist!"
    overall_status=9
fi

cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_fm_bg2ro_1d ${bgn_abs_path} \
    -o ${dfm_abs_path} \
    -a ${GPAC_ROPP_ROOT}/etc/nwp_od_an_attrb.cf \
    -l ${atm_abs_path} \
    -f \
    -d \
    -new_op \
    -comp \
    --no-ranchk

if [ -f ${dfm_abs_path} ]; then
    mv ${dfm_abs_path} ${bgn_abs_path}
else
    echo "***ERROR: ${dfm_abs_path} does not exist!"
    overall_status=9
fi

#--- 3.9 Tropopause height and tropopause parameters
if [ -f ${bgf_abs_path} ]; then
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_apps_tph_tool ${bgf_abs_path} \
        -o ${tph_abs_path} \
        -b \
        -n \
        -y \
        -t \
        --no-ranchk
    if [ -f ${tph_abs_path} ]; then
        mv ${tph_abs_path} ${bgf_abs_path}
    else
       echo "***ERROR: tph file not produced!"
       overall_status=10
    fi
fi

if [ -f ${bga_abs_path} ]; then
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_apps_tph_tool ${bga_abs_path} \
        -o ${tph_abs_path} \
        -b \
        -n \
        -y \
        -t \
        --no-ranchk
    if [ -f ${tph_abs_path} ]; then
        mv ${tph_abs_path} ${bga_abs_path}
    else
       echo "***ERROR: tph file not produced!"
       overall_status=11
    fi
fi

if [ -f ${bgo_abs_path} ]; then
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_apps_tph_tool ${bgo_abs_path} \
        -o ${tph_abs_path} \
        -b \
        -n \
        -y \
        -t \
        --no-ranchk
    if [ -f ${tph_abs_path} ]; then
        mv ${tph_abs_path} ${bgo_abs_path}
    else
       echo "***ERROR: tph file not produced!"
       overall_status=12
    fi
fi

if [ -f ${bgn_abs_path} ]; then
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_apps_tph_tool ${bgn_abs_path} \
        -o ${tph_abs_path} \
        -b \
        -n \
        -y \
        -t \
        --no-ranchk
    if [ -f ${tph_abs_path} ]; then
        mv ${tph_abs_path} ${bgn_abs_path}
    else
       echo "***ERROR: tph file not produced!"
       overall_status=12
    fi
fi

#--- 4. 1D-Var processing

#--- 4.1 Copy bgf -> bgr (for the 1D-Var processing)
if [ -f ${bgf_abs_path} ]; then
    cp ${bgf_abs_path} ${bgr_abs_path}
else
    echo "***ERROR: bgf file not produced!"
    overall_status=6
fi

if [ -f ${att_abs_path} ]; then
    #--- 4.2 Add observation errors: att -> ate
    cmd_wrapper ${GPAC_1DVAR_ROOT}/bin/1DV_add_obs_error.x _${GPAC_PID} \
        -a ${GPAC_ATTRIBUTE_CFG} \
        -attdir ${GPAC_WRKDIR} \
        -bgrdir ${GPAC_WRKDIR} \
        -outdir ${GPAC_WRKDIR} \
        -Omod TP \
        -datadir ${GPAC_1DVAR_ROOT}/etc/gras_1dvar \
        -o _${GPAC_PID}
        if [ ! -f ${ate_abs_path} ]; then
            echo "***ERROR: ${ate_abs_path} not produced!"
            overall_status=13
        fi

    #--- 4.3 Get background error correlation filename, based on number of nwp levels
    GPAC_BMATRIX=$(trn_bgr_error_cor_path ${bgf_abs_path})
    status=$?
    echo "***INFO: USING GPAC_BMATRIX: ${GPAC_BMATRIX}"
    [ $status -eq 0 ] || { echo "***ERROR: Could not find background error correlation filename";}

    if [ $status -eq 0 ] && [ -f ${bgr_abs_path} ]; then
        #--- 4.4 1D-Var processing
        # TODO: config should be defined somewhere else like the config file for ropp_pp_occ_tool

        cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_1dvar_add_bgr_error ${bgr_abs_path} \
            -c ${GPAC_BMATRIX}

        cmd_wrapper ${GPAC_1DVAR_ROOT}/bin/1DV_refrac.x  \
            -y ${ate_abs_path} \
            -b ${bgr_abs_path} \
            -o ${wet_abs_path} \
            -wfm ${wfm_abs_path} \
            --obs-corr ${cor_abs_path} \
            -c ${GPAC_1DVAR_ROOT}/etc/gras_1dvar/1DV_config.cf \
            -a ${GPAC_ATTRIBUTE_CFG} \
            --bg-corr ${GPAC_BMATRIX} \
            -cvS ${cvs_abs_path} \
            -grH ${grh_abs_path} \
            -J_qc 5.0 \
            -comp

        if [ -f ${wfm_abs_path} ]; then
            #--- 4.5 Change name of background file: bgr -> bge
            mv ${bgr_abs_path} ${bge_abs_path}
            #--- 4.6 Tropopause height and tropopause parameters
            cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp_apps_tph_tool ${wfm_abs_path} \
                -o ${tph_abs_path} \
                -a ${GPAC_ATTRIBUTE_CFG} \
                -t \
                --no-ranchk
            mv ${tph_abs_path} ${wfm_abs_path}
        else
            echo "***ERROR: wfm file not produced!"
            overall_status=14
        fi
    else
        echo "***INFO: Skipping 1dvar processing."
    fi
else
    echo "***ERROR: ${att_abs_path} not produced! Skipping 1dvar"
    overall_status=15
fi

#--- 5. QC handling
# TODO: handle errors from qc. Handle archiving of qc-file.

#--- 5.1 First perform QC methods defined in config
gpac_qc qc  \
    --bgr ${bgf_abs_path} \
    --levels 1b 2a \
    -o ${qcr_abs_path} \
    ${qcr_settings} \
    ${atm_abs_path}

status=$?
[ $status -eq 0 ] || { echo "***ERROR: gpac_qc level 1b, 2a failed!"; exit 224; }

gpac_qc qc  \
    --levels 2b \
    -o ${qcr_abs_path} \
    ${qcr_settings} \
    ${wet_abs_path}

status=$?
[ $status -eq 0 ] || { echo "***ERROR: gpac_qc level 2b failed!"; exit 224; }

#--- 5.2 Now determine the total pcd value from QC and obs files
#--- The additional files we want to set pcd value in are added in --add-files
gpac_qc flag  \
    --qcr ${qcr_abs_path} \
    --obs-files ${occ_abs_path} ${atm_abs_path} ${wet_abs_path} \
    --add-files ${att_abs_path} ${ate_abs_path} ${wfm_abs_path} \
    --qc-rules

status=$?
[ $status -eq 0 ] || { echo "***ERROR: gpac_qc set pcd failed!"; exit 224; }

#--- 6. Generate dis and BUFR files

#--- 6.1 The dis file
if [ -f ${att_abs_path} ]; then
    if [ -f ${wet_abs_path} ]; then
        cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp2ropp ${wet_abs_path} \
        -o ${dis_abs_path} \
        -c ${att_abs_path} \
        -b ${GPAC_ATTRIBUTE_CFG} \
        -s \
        --no-ranchk
    else
        cp ${att_abs_path} ${dis_abs_path}
    fi

    #--- 6.2 Store dis as BUFR
    cmd_wrapper ${GPAC_ROPP_ROOT}/bin/ropp2bufr ${dis_abs_path} \
        -o ${bfr_abs_path}

    if [ ! -f ${bfr_abs_path} ]; then
        echo "***ERROR: bfr file not produced"
        overall_status=16
    fi
else
   echo "***INFO: Skipping dis and bfr - att file not produced"
fi

# Can we skip pnc generation if some previous files not produced?
#--- 7. Generate pnc files
cmd_wrapper ${GPAC_CLIM_ROOT}/bin/rom_profs_ropp2pnc.x \
    -occfile ${occ_abs_path} \
    -atmfile ${atm_abs_path} \
    -wetfile ${wfm_abs_path} \
    -bgrfile ${bgf_abs_path} \
    -bgefile ${bge_abs_path} \
    -pncfile ${pnc_abs_path} \
    -ppcfile ${ppc_abs_path}

if [ ! -f ${pnc_abs_path} ]; then
    echo "***ERROR: pnc file not produced"
    overall_status=17
fi
if [ ! -f ${ppc_abs_path} ]; then
    echo "***ERROR: ppc file not produced"
    overall_status=18
fi

echo "***INFO: Final status: $overall_status"

# return final status
exit $overall_status
