#!/bin/bash

set -e
#set -x

usage() {
    cat >&2 <<EOF
Usage: $0 [OPTION] <parameters file>
Options:
    -h  print this help
    -n  dry-run mode (for debugging)
    -c  (continue) do not overwrite previous results
    -z  compress output files with gzip
EOF
    exit $1
}

log() {
    echo "-#- $@" >&2
}

die() {
    echo "ERROR: $@" >&2
    exit 2
}

variable_check() {
    eval test -n "\${$1}" || die "undefined $1"
}

array_check() {
    eval test "\${#$1}" -gt 0 || die "undefined $1"
}

# read args
overwrite=1
debug=0
compress=0
while getopts "chnz" c; do
    case "$c" in
        'c') overwrite=0 ;;
        'h') usage 0 ;;
        'n') debug=1 ;;
        'z') compress=1 ;;
        '?') usage 1 ;;
    esac
done
shift $((OPTIND - 1))
[ $# -eq 1 ] || usage 1
parameters="$1"

log "Running: $0 $@"
log "Hostname: $(hostname -f)"

declare -a TOPOLOGIES ALGORITHMS PLATFORMS COMMON_OPTS MORE_ARGS

# read parameters
log "Reading parameters from \"$1\"."
source "$parameters" || die "cannot read parameters file: \"$parameters\""

array_check TOPOLOGIES
array_check ALGORITHMS
array_check PLATFORMS
variable_check NHOSTS
variable_check LOAD
variable_check DEADLINE

# default values
: ${RESULTS:=$PWD/results}
: ${LOBA:=$PWD/loba}

COMMON_OPTS=(
    --cfg=contexts/factory:raw
    "${MORE_ARGS[@]}"
)

log "Results put in: \"$RESULTS\"."

[ $debug = 1 ] && log "Running in dry-run mode"

outfile() {
    echo "$*" | sed 's,[^ ]*/,,g;s/\.xml//;y/ /_/'
}

summary() {
    gzip -cdf "$@" \
				| sed -n '\!^\[main/INFO\] ,----\[ Results \]!,${
        /send\|recv\|wall clock\|Simulation succeeded/d;p;
      }'
}

if [ $compress = 1 ]; then
    outsuffix=".gz"
else
    outsuffix=""
fi

for plat in "${PLATFORMS[@]}"; do
    tmp=$(basename "$plat" ".xml")
    plat_output="$RESULTS/plat_$tmp"
    for topo in "${TOPOLOGIES[@]}"; do
        topo_output="$plat_output/topo_$topo"
        [ $debug = 0 ] && mkdir -p "$topo_output"
 #       for lr in "1" "N"; do
 #           case "$lr" in
 #               "1") loadinit=( ) ;;
 #               "N") loadinit=( "-R" "-r42" ) ;;
 #               *) die "internal error (lr = \"$lr\")" ;;
 #           esac
						for mode in "R" "Z"; do
								case "$mode" in
										"R") computemode=( );;
										"Z") computemode=( "-Z" );;
										*) die "internal error (mode = \"$mode\")" ;;
								esac
								for algo in "${ALGORITHMS[@]}"; do
										algo_output="$topo_output/algo_$algo"
										args=(
												-T"$topo"
												-a"$algo"
												-N"$NHOSTS"
												-L"$LOAD"
												-t"$DEADLINE"
#												"${loadinit[@]}"
												"${computemode[@]}"
												"$plat"
										)

										for bk in "plain" "bookkeeping"; do
												cmd=( "$LOBA" "${COMMON_OPTS[@]}" )
												case "$bk" in
														"plain") : ;;
														"bookkeeping") cmd+=( "-b" ) ;;
														*) die "internal error (bk = \"$bk\")" ;;
												esac
												out="${algo_output}_${bk}_${mode}.out"
												outf="$out$outsuffix"
												cmd+=( "${args[@]}" )
												log "Run: ${cmd[@]}"$'\n'"... &> $outf"
												if [ $overwrite = 0 -a -e "$outf" ]; then
														log "already run !"
														summary "$outf"
														continue
												fi
												if [ $debug = 1 ]; then
														log "skipped (dry-run)"
														continue
												fi
												rm -f "$outf";
												echo "# ${cmd[@]}" > "$out"
												if "${cmd[@]}" >> "$out" 2>&1; then
														summary "$out"
												else
														grep -v '/INFO\]' "$out"
												fi
												if [ $compress = 1 ]; then
														log "Compress output file."
														gzip --best "$out"
												fi
										done
#								done
            done
        done
    done
done