#---------------------------------*- sh -*-------------------------------------
# =========                 |
# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
#  \\    /   O peration     | Website:  https://openfoam.org
#   \\  /    A nd           | Copyright (C) 2022 OpenFOAM Foundation
#    \\/     M anipulation  |
#------------------------------------------------------------------------------
# License
#     This file is part of OpenFOAM, licensed under GNU General Public License
#     <http://www.gnu.org/licenses/>.
#
# Script
#     RunFunctionsPF
#
# Description
#     Miscellaneous functions for running petroFOAM cases
#     Based on OpenFOAM original RunFunctions
#
# Author and Copyrights: Wikki Brasil C E LTDA
# Code implementation:   Jovani Favero
# Date:                  October, 2021
# Last Update:           October, 2023
#------------------------------------------------------------------------------

#
# Run given application in parallel with logfile output.
# The preexistence of the log file prevents rerunning.
#
runParallel()
{
    local appRun logFile logMode nProcs logCompress logZip logOpt

#    local MPI_ARGS="-machinefile $PBS_NODEFILE -nooversubscribe --bind-to none -mca plm ^rshd"
#    local MPI_ARGS="-nooversubscribe --bind-to none -mca plm ^rshd"

#    Obs.: use MPIRUN and MPIARGS from external declaration, from petrofoam admin via bashrc file
#    but if not defined, define it here as mpirun
    if [ -z ${MPIRUN} ]; then export MPIRUN=mpirun; fi

    # Any additional parsed arguments (eg, decomposeParDict)
    local appArgs="-parallel"

    # Parse options until executable is encountered
    while [ $# -gt 0 -a -z "$appRun" ]
    do
        case "$1" in
            -a | -append)
                logMode=append
                ;;
            -o | -overwrite)
                logMode=overwrite
                ;;
            -m | -nolog)
                logOpt=nolog
                ;;
            -c | -compress)
                logCompress=compress
                ;;
            -s | -suffix)
                logFile=".$2"
                shift
                ;;
            -n | -np)
                nProcs="$2"
                shift
                ;;
            -decomposeParDict)
                appArgs="$appArgs $1 $2"
                nProcs=$(getNumberOfProcessors "$2")
                shift
                ;;
            '')
                ;;
            *)
                appRun="$1"
                ;;
        esac
        shift
    done

    [ -n "$nProcs" ] || nProcs=$(getNumberOfProcessors system/decomposeParDict)

    local appName="${appRun##*/}"

    if [ "$logCompress" = compress ]
    then
        if [ "$logMode" = append ]
        then
            echo "Compression and Append cannot be selected simultaneously," \
                 "choose just one of these options, going to run append without compression"
        elif [ "$logOpt" = nolog ]
        then
            echo "Compression and no log option cannot be selected simultaneously," \
                 "choose just one of these options, going to run nolog without compression"
        else
            logZip=".gz"
        fi
    fi

    logFile="log.$appName$logFile$logZip"

    if [ -f "$logFile" -a -z "$logMode" ]
    then
        echo "$appName already run on $PWD:" \
             "remove log file '$logFile' to re-run"
    else
        echo "Running $appRun ($nProcs processes) on $PWD "
        if [ "$logMode" = append ]
        then
        (
            if [ "$logOpt" = nolog ]
            then
            (
                echo "Running with no log option "
                $MPIRUN -np $nProcs $MPIARGS $appRun $appArgs "$@" 1> /dev/null 2>> $logFile
            )
            else
            (
                $MPIRUN -np $nProcs $MPIARGS $appRun $appArgs "$@" </dev/null >> $logFile 2>&1
            )
            fi
        )
        elif [ "$logCompress" = compress ] && [ "$logOpt" != nolog ]
        then
        (
            $MPIRUN -np $nProcs $MPIARGS $appRun $appArgs "$@" </dev/null 2>&1 | gzip -9 > $logFile
        )
        else
        (
            if [ "$logOpt" = nolog ]
            then
            (
                echo "Running with no log option "
                $MPIRUN -np $nProcs $MPIARGS $appRun $appArgs "$@" 1> /dev/null 2> $logFile
            )
            else
            (
                $MPIRUN -np $nProcs $MPIARGS $appRun $appArgs "$@" </dev/null > $logFile 2>&1
            )
            fi
        )
        fi
    fi
}

#
# Run given application assuming running with singularity and with logfile output.
# The preexistence of the log file prevents rerunning.
#
runParallelSing()
{
    local appRun logFile logMode nProcs logCompress logZip logOpt

    # Any additional parsed arguments (eg, decomposeParDict)
    local appArgs="-parallel"

    # Parse options until executable is encountered
    while [ $# -gt 0 -a -z "$appRun" ]
    do
        case "$1" in
            -a | -append)
                logMode=append
                ;;
            -o | -overwrite)
                logMode=overwrite
                ;;
            -m | -nolog)
                logOpt=nolog
                ;;
            -c | -compress)
                logCompress=compress
                ;;
            -s | -suffix)
                logFile=".$2"
                shift
                ;;
            -n | -np)
                nProcs="$2"
                shift
                ;;
            -decomposeParDict)
                appArgs="$appArgs $1 $2"
                nProcs=$(getNumberOfProcessors "$2")
                shift
                ;;
            '')
                ;;
            *)
                appRun="$1"
                ;;
        esac
        shift
    done

    [ -n "$nProcs" ] || nProcs=$(getNumberOfProcessors system/decomposeParDict)

    local appName="${appRun##*/}"

    if [ "$logCompress" = compress ]
    then
        if [ "$logMode" = append ]
        then
            echo "Compression and Append cannot be selected simultaneously," \
                 "choose just one of these options, going to run append without compression"
        elif [ "$logOpt" = nolog ]
        then
            echo "Compression and no log option cannot be selected simultaneously," \
                 "choose just one of these options, going to run nolog without compression"
        else
            logZip=".gz"
        fi
    fi

    logFile="log.$appName$logFile$logZip"

    if [ -s "$logFile" -a -z "$logMode" ]
    then
        echo "$appName already run on $PWD:" \
             "remove log file '$logFile' to re-run"
    else
        echo "Running $appRun ($nProcs processes) on $PWD "
        if [ "$logMode" = append ]
        then
        (
            if [ "$logOpt" = nolog ]
            then
            (
                echo "Running with no log option "
                $appRun $appArgs "$@" 1> /dev/null 2>> $logFile
            )
            else
            (
                $appRun $appArgs "$@" </dev/null >> $logFile 2>&1
            )
            fi
        )
        elif [ "$logCompress" = compress ] && [ "$logOpt" != nolog ]
        then
        (
            $appRun $appArgs "$@" </dev/null 2>&1 | gzip -9 > $logFile
        )
        else
        (
            if [ "$logOpt" = nolog ]
            then
            (
                echo "Running with no log option "
                $appRun $appArgs "$@" 1> /dev/null 2> $logFile
            )
            else
            (
                $appRun $appArgs "$@" </dev/null > $logFile 2>&1
            )
            fi
        )
        fi
    fi
}

#
# Prinf an info message
#
printInfo ()
{
    echo ""
    echo "$1"
    echo ""
}

#
# Run a check on a given status
#
checkReturn ()
{
    if [ $# -lt 3 ]; then
        printInfo "ERROR! usage: checkReturn <error code>  <msg 1>  <msg 2>"
        exit 1
    fi
    if [ $1 -eq 0 ]
    then
        echo ""
        echo " $2: OK! "
        echo ""
    else
        echo ""
        echo " $2: ERROR! "
        echo ""
        echo "$3" >> ./logErrors.out
        exit 1
    fi
}

#
# Run a check on file log errors return
#
checkLogReturn ()
{
    if [ $# -lt 2 ]; then
        printInfo "ERROR! usage: checkLogReturn  <msg 1>  <msg 2>"
        exit 1
    fi
    python3 $MULTIPHASE_BIN/pythonScripts/checkLogErrorExitStatus.py
    R_ERROR=$?
    checkReturn $R_ERROR "$1" "$2"
}

#
# Run a check on file log errors return and clean case if errors are found
#
checkLogReturnClean ()
{
    if [ $# -lt 2 ]; then
        printInfo "ERROR! usage: checkLogReturnClean  <msg 1>  <msg 2>"
        exit 1
    fi
    python3 $MULTIPHASE_BIN/pythonScripts/checkLogErrorExitStatus.py
    R_ERROR=$?
    if [ $R_ERROR -ne 0 ]; then
        echo "Cleaning case before exiting ..."
        ./CleanCase
    fi
    checkReturn $R_ERROR "$1" "$2"
}

#
# Run a check on file log errors
#
checkLogError ()
{
    if [ $# -lt 2 ]; then
        printInfo "ERROR! usage: checkLogError  <file name to search>  <msg>"
        exit 1
    fi
    if [ -f $1 ]; then
        echo ""
        echo " $2: ERROR! "
        echo "File $1 found, exiting ..."
        echo ""
        exit 1
    else
        echo ""
        echo " $2: OK! "
        echo ""
    fi
}

#
# Run a check on file log errors and clean case if errors are found
#
checkLogErrorClean ()
{
    if [ $# -lt 2 ]; then
        printInfo "ERROR! usage: checkLogErrorClean  <file name to search>  <msg>"
        exit 1
    fi
    if [ -f $1 ]; then
        echo ""
        echo " $2: ERROR! "
        echo "File $1 found, cleaning case and exiting ..."
        echo ""
        ./CleanCase
        exit 1
    else
        echo ""
        echo " $2: OK! "
        echo ""
    fi
}
