#!/bin/bash
set -o errexit
set -o pipefail

# Log function:
shopt -s expand_aliases
alias 'stop_xtrace={ set +o xtrace; } 2> /dev/null'
# See: https://unix.stackexchange.com/questions/253381/inline-debug-xtrace-in-scripts#253505
log_()
{
    echo "===== $1"
    set -o xtrace
}
alias 'log=stop_xtrace; log_'
set -o xtrace


env_name="$1"
vagrant_source="$2"
extra_vagrant_file="$3"
vagrant_dir="$HOME/vagrant/$env_name"

destroy_env()
{
    pushd "$vagrant_dir"
    timeout --kill-after=10s 30s vagrant destroy --force || true
    popd
    rm -r "$vagrant_dir"
}

start_env()
{
    pushd "$vagrant_dir"
    local attempt=0
    local max_attempts=3
    local result=0
    while : ; do
        ((attempt = attempt + 1))

        set +o errexit +o pipefail
        (set -o errexit -o pipefail; vagrant up 2>&1 | tee log)
        result=$?
        set -o errexit -o pipefail

        if (( result == 0 )); then
            break
        fi

        if (( attempt > max_attempts )); then
            log 'Too many start attempts.'
            break
        fi

        if grep -F 'An SSL error occurred while connecting to WinRM.' >/dev/null <log; then
            log "WinRM connection failed. Attempt $attempt/$max_attempts .."
        else
            break
        fi
    done
    popd
    return $result
}

if [[ ! "$vagrant_dir/.source1" -ef "$vagrant_source" ]] ||
   [[ ! "$vagrant_dir/.source2" -ef "$extra_vagrant_file" ]]; then
    log 'Rebuilding environment because its description changed'

    if [[ -d "$vagrant_dir" ]]; then # directory exists already
        log 'Destroying old environment'
        destroy_env
    fi

    log 'Building new environment'
    mkdir -p "$vagrant_dir"
    trap destroy_env EXIT
    pushd "$vagrant_dir"
    ln -s "$vagrant_source"/* ./
    ln -s "$vagrant_source" '.source1' # this is used to detect changes
    ln -s "$extra_vagrant_file" '.source2'
    rm Vagrantfile
    cp --no-preserve=mode "$vagrant_source/Vagrantfile" Vagrantfile
    cat "$extra_vagrant_file" >> Vagrantfile
    start_env
    vagrant halt
    popd
    trap - EXIT
fi

pushd "$vagrant_dir"
stop_environment()
{
    vagrant halt || true
    #vagrant snapshot delete 'sandbox' || true
}

log 'Running environment'
stop_environment
#vagrant snapshot save 'sandbox'
start_env
trap stop_environment EXIT
while true; do # run watchdog in regular intervals
    sleep 1m
    if vagrant status | grep -F 'poweroff' > /dev/null; then
        log 'Environment stopped'
        exit 0
        #log 'Environment stopped unexpectedly'
        #exit 1
    fi
done
popd
