#! /bin/bash

status=1
command="$0 $*"
tmpdir=${TMPDIR:-/tmp}
stdin_file="$tmpdir/plough$$_stdin.yaml"
trap 'exit $status' 0 1 2 15

read_stdin=0
config_file="/dev/null"
variables=""
use_grid_engine=0
cross_apply=0
queue=""
qsub_options=""
parallelisation_factor=${TRACTOR_PLOUGH_THREADS:-1}
debug=0
repetitions=0
working_dir=${TRACTOR_WORKING_DIR:-.}
distribution_version="ersion unknown"

tractor_flags=""
tractor_options=""

usage()
{
    echo "plough (program v3.5.0, distribution v$distribution_version)"
    echo "Plough through your TractoR analysis!"
    echo
    echo "Usage: plough [-GXDI] -C config_file [-V variable_name] [-R repetitions]"
    echo "              [-Q grid_queue] [-O grid_options] [-P factor]"
    echo "              [tractor_flags] script [arg1 [arg2 ...]]"
    echo "       plough -H"
    echo
    echo "  -H          Display this usage information and exit"
    echo "  -G          Schedule parallel jobs on the Oracle (formerly Sun) Grid"
    echo "              Engine. The 'qsub' executable must be on your PATH"
    echo "  -X          Cross-apply the loop variables, taking each combination in"
    echo "              turn"
    echo "  -D          Produce debugging output from plough. This does not imply"
    echo "              that tractor will be called with '-d'; that flag should also"
    echo "              be given if required"
    echo "  -I          Read values of the 'Input' variable from standard input."
    echo "              Values or file names containing whitespace cannot be passed"
    echo "              this way"
    echo "  -C file     Specify a configuration file in YAML format, defining"
    echo "              variables for use in the command. Can be specified more than"
    echo "              once, and is required unless '-I' is given"
    echo "  -V var      Specify a variable over which the loop will be run. It must"
    echo "              be defined in a configuration file"
    echo "  -R reps     Specify the number of repetitions to be run. If specified,"
    echo "              this takes priority over the '-V' and '-X' options, and the"
    echo "              configuration file is passed unmodified to each instance"
    echo "  -Q queue    Specify the grid engine queue name to submit to"
    echo "  -O options  Specify any addition grid engine options required. These"
    echo "              must be quoted if they include any spaces"
    echo "  -P factor   Set the parallelisation factor for multicore systems."
    echo "              Ignored if '-G' is specified"
    echo
    echo "The specified TractoR script is called with different combinations of"
    echo "parameters. By default, the loop is over all configuration variables in"
    echo "the file(s) specified using the '-C' flag, in parallel. With the '-X' flag"
    echo "every combination of values is used instead. The calls can be parallel-"
    echo "ised, either across cores (using the '-P' flag), or through a grid engine"
    echo "scheduler (using '-G')."
    echo
    echo "Flags are uppercase to avoid conflicting with those for tractor, but '-H'"
    echo "and '-C' are shared, and therefore case-insensitive."
    echo
}

if [ -z "${TRACTOR_HOME}" ]; then
    echo "Note: The TRACTOR_HOME environment variable is not set; it will be guessed"
    TRACTOR_HOME=`echo $0 | sed 's/\/bin\/tractor$//'`
else
    # Replace the specified path with a fully-qualified version
    TRACTOR_HOME=`unset CDPATH; cd "$TRACTOR_HOME" && pwd`
fi
export TRACTOR_HOME

[ -f "${TRACTOR_HOME}/VERSION" ] && distribution_version=`cat "${TRACTOR_HOME}/VERSION"`

while getopts ":HhGXDIC:c:V:R:Q:O:P:v:a:w:" opt; do
    case "$opt" in
        [Hh]) usage; status=0; exit ;;
        G) use_grid_engine=1 ;;
        X) cross_apply=1 ;;
        D) debug=1 ;;
        I) read_stdin=1 ;;
        [Cc]) config_file="$config_file:$OPTARG" ;;
        V) variables="$variables,$OPTARG" ;;
        R) repetitions=$OPTARG ;;
        Q) queue=$OPTARG ;;
        O) options="$options $OPTARG" ;;
        P) parallelisation_factor=$OPTARG ;;
        [vaw]) tractor_flags="$tractor_flags -$opt $OPTARG" ;;
        ?) tractor_flags="$tractor_flags -$OPTARG" ;;
    esac
done

shift "$(($OPTIND-1))"

[ $# -eq 0 ] && {
    echo "Error: No script name given. Type \"plough -H\" for help" 1>&2
    exit
}

[ $read_stdin -eq 1 ] && {
    stdin_empty=1
    text="Input: ["
    while read line; do
        for value in $line; do
            stdin_empty=0
            text="$text \"$value\","
        done
    done
    
    [ $stdin_empty -eq 0 ] && {
        echo "$text" | sed 's/,$/ ]/' >$stdin_file
        config_file="$stdin_file:$config_file"
    }
}

[ "$config_file" = /dev/null ] && {
    echo "Error: No config file name given. Type \"plough -H\" for help" 1>&2
    exit
}

[ -z "$R" ] && R=R

script_name=`echo $1 | sed 's/\.R$//'`
shift
tractor_options="$@"

[ -d "${TRACTOR_HOME}/lib/R" ] && export R_LIBS="${TRACTOR_HOME}/lib/R"

[ -z $COLUMNS ] && {
    type tput >/dev/null 2>&1
    tput_available=$?
    [ $tput_available -eq 0 ] && COLUMNS=`tput cols` || COLUMNS=80
    export COLUMNS
}

[ $debug -eq 1 ] && echo "library(utils); library(tractor.utils); ploughExperiment('$script_name', '$config_file', '$variables', '$tractor_flags', '$tractor_options', $use_grid_engine, $cross_apply, '$queue', '$options', $parallelisation_factor, $debug, $repetitions)"

echo "library(utils); library(tractor.utils); ploughExperiment('$script_name', '$config_file', '$variables', '$tractor_flags', '$tractor_options', $use_grid_engine, $cross_apply, '$queue', '$options', $parallelisation_factor, $debug, $repetitions)" | "$R" --slave --vanilla 2>&1

status=0
