#!/usr/bin/env bash
# Author Jan Christoph Uhde

main(){
    source_file=~/.tmux_starter_suites #may not contain spaces
    if [[ -f $source_file ]]; then
        . $source_file
    fi

    local suite=${1:-all}
    shift

    local tasks="suite_$suite"
    type -t function $tasks &>/dev/null|| die "suite $suite not defined"
    echo "using function name: $tasks"
    local session_name="$($tasks 'name')"
    echo "using session name: $session_name"
    local panes=$($tasks 'num')
    echo "using $panes panes"
    kill_old_session "$session_name"
    tmux new-session -d -s "$session_name" || die "unable to spawn session"
    local rows=$(( (panes+1) / 2 ))
    local cols=$((((panes>1)) * 2))
    spawn_panes "$session_name" $rows $cols
    tmux select-pane -t $session_name.0
    execute_tasks "$(pwd)" "$tasks" "$@"
    tmux -2 attach-session -t $session_name
}

# task definitions

suite_all(){
    local count="$1"
    shift 1
    local args="$@"
    local args_default=( '--cluster' 'false' )

    local tests=""
    case $count in
        num)
            echo "12"
            return
        ;;
        name)
            echo "test_all"
            return
        ;;
        delay)
            return
        ;;
        0)
            echo "./scripts/quickieTest.sh ${args[@]} && exit 0"
            return
        ;;
        1)
            tests="shell_server"
        ;;
        2)
            tests="shell_client"
        ;;
        3)
            tests="shell_server_aql --testBuckets 2/0"
        ;;
        4)
            tests="shell_server_aql --testBuckets 2/1"
        ;;
        5)
            tests="http_server"
        ;;
        6)
            tests="server_http"
        ;;
        7)
            tests="dump importing"
        ;;
        8)
            tests="export arangobench upgrade"
        ;;
        9)
            tests="replication_sync replication_static"
        ;;
        10)
            tests="replication_ongoing http_replication shell_replication"
        ;;
        11)
            tests="agency cluster_sync"
        ;;
        *)
    esac

    echoerr "./scripts/unittest $tests ${args_default[@]} ${args[@]} && exit 0"
    echo    "./scripts/unittest $tests ${args_default[@]} ${args[@]} && exit 0"
}

portrange() {
    local count="$1"
    local portStart=1240
    local portOffset=20
    echo "--minPort $(( portStart + count * portOffset )) --maxPort $(( portStart + (count + 1) * portOffset - 1))"
}

## suite_all_cluster(){
##     local count="$1"
##     shift 1
##     local args="$@"
##     local args_default=( '--cluster' 'true' )
## 
##     local tests=""
##     case $count in
##         num)
##             echo "12"
##             return
##         ;;
##         name)
##             echo "test_all_cluster"
##             return
##         ;;
##         delay)
##             echo "10"
##             return
##         ;;
##         0)
##             echo "./scripts/quickieTest.sh ${args[@]} && exit 0"
##             return
##         ;;
##         1)
##             tests="shell_server $(portrange $count)"
##         ;;
##         2)
##             tests="shell_client $(portrange $count)"
##         ;;
##         3)
##             tests="shell_server_aql --testBuckets 3/0 $(portrange $count)"
##         ;;
##         4)
##             tests="shell_server_aql --testBuckets 3/1 $(portrange $count)"
##         ;;
##         5)
##             tests="shell_server_aql --testBuckets 3/2 $(portrange $count)"
##         ;;
##         6)
##             tests="http_server $(portrange $count)"
##         ;;
##         7)
##             tests="ssl_server $(portrange $count)"
##         ;;
##         8)
##             tests="server_http $(portrange $count)"
##         ;;
##         9)
##             tests="dump $(portrange $count)"
##         ;;
##         10)
##             tests="agency $(portrange $count)"
##         ;;
##         11)
##             tests="resilience $(portrange $count)"
##         ;;
##         *)
##             echo "exit 0"
##             return
##     esac
## 
##     echo "./scripts/unittest $tests ${args_default[@]} ${args[@]} && exit 0"
## }


suite_all_cluster(){
    local count="$1"
    shift 1
    local args="$@"
    local args_default=( '--cluster' 'true' )

    local tests=""
    case $count in
        num)
            echo "6"
            return
        ;;
        name)
            echo "test_all_cluster"
            return
        ;;
        delay)
            echo "10"
            return
        ;;
        0)
            echo "./scripts/quickieTest.sh ${args[@]} && exit 0"
            return
        ;;
        1)
            tests="shell_server $(portrange $count)"
        ;;
        2)
            tests="shell_client $(portrange $count)"
        ;;
        3)
            tests="shell_server_aql $(portrange $count)"
        ;;
        4)
            tests="http_server ssl_server server_http $(portrange $count)"
        ;;
        5)
            tests="dump agency resilience $(portrange $count)"
        ;;
        *)
            echo "exit 0"
            return
    esac

    echo "./scripts/unittest $tests ${args_default[@]} ${args[@]} && exit 0"
}

suite_all_rocksdb(){
    local count="$1"
    shift 1
    local args="$@"

    case $count in
        name)
            echo "test_all_rocksdb"
            return
        ;;
        *)
            suite_all "$count" "--storageEngine rocksdb" "${args[@]}"
        ;;
    esac
}

suite_all_rocksdb_cluster(){
    local count="$1"
    shift 1
    local args="$@"

    case $count in
        name)
            echo "test_all_rocksdb_cluster"
            return
        ;;
        *)
            suite_all_cluster "$count" "--storageEngine rocksdb" "${args[@]}"
        ;;
    esac
}
# tmux
kill_old_session(){
    local session_name="$1"
    if tmux has-session -t $session_name 2> /dev/null; then
        echo "Session $session_name exists. Kill it? [y/N]"
        read kill_sess
        echo "killsess '$kill_sess'"
        if [[ ($kill_sess == "y") || ($kill_sess == "Y") ]]; then
            tmux kill-session -t $session_name
        else
            die "Session not created because it already exists. Exiting."
        fi
    fi
}

spawn_panes(){
    local session_name="$1"
    local rows=$2
    local cols=$3

    # Create rows
    local row=$rows
    while (( row > 1 )); do
        frac=$(echo "scale=2;1/$row" | bc)
        percent=$(echo "($frac * 100)/1" | bc)
        tmux select-pane -t $session_name.0 || die "could not select pane 0 of session $session_name"
        tmux split-window -v -p $percent
        ((row--))
    done

    # Create columns
    if ((cols > 1)); then
        local count=$((rows - 1))
        while ((count >= 0)); do
            tmux select-pane -t $session_name.$count || die "could not select pane $session_name.$count" 
            tmux split-window -h -p 50
            (( count-- ))
        done
    fi
}

execute_tasks(){
    cd $1 || die
    local tasks="$2"
    shift 2
    local args="$@"
    local count=0
    local delay=""
    delay="$($tasks 'delay')"
    while (( count < $($tasks 'num') )); do
        local exec_cmd="$($tasks $count "${args[@]}")"
        echo "running: ${exec_cmd[@]}"
        if [[ -n "$delay" ]]; then
            echo "sleep for $delay"
            sleep "$delay"
        fi
        tmux send-keys -t $session_name.$count "${exec_cmd[@]}" Enter
        (( count++ ))
    done
}

# helper
echoerr() { printf "%s\n" "$*" >&2; }

die(){
    echo "FATAL: ${1-this should not happen}"
    exit 1
}


cores(){
    # Determine automatically on Mac or Linux
    if [[ $(uname) == 'Darwin' ]]; then
        echo "$(sysctl hw.ncpu | awk '{print $2}')"
    else
        echo "$(nproc)"
    fi
}

main "$@"
exit 0
