#!/bin/bash

# Unofficial Bash Strict Mode (http://redsymbol.net/articles/unofficial-bash-strict-mode/)
set -euo pipefail
IFS=$'\n\t'
PROG="$(basename "$0")"


function set_defaults()
{
    BASE_CONFIG='base'
}


function error()
{
    if (( $# > 0 ));
    then
        echo "$PROG: error:" "$@"
    else
        echo
    fi
} >&2


function bail_out()
{
    error "$@"
    exit 1
}


function bail_out_usage()
{
    error "$@"
    error
    print_usage
    exit 1
}


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


function print_usage()
{
    echo "USAGE:  $PROG [-h] [--notify] <dataset>/<reads> [--] [<snakemake-args>...]"
} >&2


function print_help()
{
    print_usage
    echo
    echo 'Run snakemake for dentist with required parameters for the given'
    echo '<dataset>/<reads> combination. Argument processing stops at -- if given'
    echo
    echo 'Positional arguments:'
    echo ' <dataset>         Name of reference assembly, e.g. h_sapiens.'
    echo ' <reads>           Type of reads, e.g. simulated-pb.'
    echo ' <snakemake-args>  Additional arguments passed to snakemake, e.g. --profile=slurm.'
    echo
    echo 'Optional arguments:'
    echo ' --no-notify, -N   Do not send a notification via email.'
    echo ' --base-config=<config>'
    echo '                   Use <config> as base config file (default: base).'
    echo ' --help, -h        Prints this help.'
    echo ' --usage           Print a short command summary.'
    echo ' --version         Print software version.'
} >&2


function print_version()
{
    echo "$PROG v0"
    echo
    echo "Copyright © 2019, Arne Ludwig <arne.ludwig@posteo.de>"
} >&2


function stop_processing()
{
    STOP_PROCESSING=1
}


function parse_args()
{
    ARGS=()
    for ARG in "$@";
    do
        if [[ ! -v STOP_PROCESSING ]] && [[ "${ARG:0:1}" == - ]];
        then
            case "$ARG" in
                --)
                    stop_processing
                    ;;
                -N|--no-notify)
                    NO_NOTIFY=1
                    ;;
                --base-config=*)
                    BASE_CONFIG="${ARG#--base-config=}"
                    ;;
                -h|--help)
                    print_help

                    exit
                    ;;
                --usage)
                    print_usage

                    exit
                    ;;
                --version)
                    print_version

                    exit
                    ;;
                *)
                    stop_processing

                    ARGS+=( "$ARG" )
                    ;;
            esac
        else
            ARGS+=( "$ARG" )
        fi
    done

    (( ${#ARGS[*]} >= 1 )) || bail_out_usage "<dataset>/<reads> is missing"

    DATASET="${ARGS[0]%/*}"
    READS="${ARGS[0]##*/}"
    unset 'ARGS[0]'
}


function prepare_snakemake_args()
{
    SNAKEMAKE_ARGS=(
        "--configfile=config/$BASE_CONFIG.yml"
        "config/$DATASET/$READS.yml"
    )

    [[ ! -v ARGS ]] || SNAKEMAKE_ARGS+=( "${ARGS[@]}" )
}


function notify_mail()
{
    local JOB="dentist $DATASET/$READS"

    {
        echo "Your job '$JOB' has terminated ($EXIT). Additional info:"
        echo
        echo "using $DENTIST_VERSION"
        echo "snakemake" "${SNAKEMAKE_ARGS[@]}"
    } | mail -s "$JOB ($EXIT)" ludwig@mpi-cbg.de
}


function main()
{
    set_defaults
    parse_args "$@"
    prepare_snakemake_args

    DENTIST_VERSION="$( dentist --version 2>&1 )"
    DENTIST_VERSION="$( head -n1 <<<"$DENTIST_VERSION" )"
    log "using $DENTIST_VERSION"

    log "snakemake" "${SNAKEMAKE_ARGS[@]}"
    EXIT=0
    snakemake "${SNAKEMAKE_ARGS[@]}" || EXIT="$?"

    [[ -v NO_NOTIFY ]] || notify_mail

    exit "$EXIT"
}


main "$@"
