#!/bin/bash

set -eu -o pipefail

assertNotEmpty() {
    : "${!1:? "$1 is not set."}"
}

readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)"
export JSON="${SOURCE_DIR}/node_modules/.bin/json"

revision=$(git rev-parse HEAD)
box_name=""
server_id=""
server_ip=""
destroy_server="yes"
deploy_env="dev"

# Only GNU getopt supports long options. OS X comes bundled with the BSD getopt
# brew install gnu-getopt to get the GNU getopt on OS X
[[ $(uname -s) == "Darwin" ]] && GNU_GETOPT="/usr/local/opt/gnu-getopt/bin/getopt" || GNU_GETOPT="getopt"
readonly GNU_GETOPT

args=$(${GNU_GETOPT} -o "" -l "revision:,regions:,size:,name:,no-destroy,env:" -n "$0" -- "$@")
eval set -- "${args}"

while true; do
    case "$1" in
    --env) deploy_env="$2"; shift 2;;
    --revision) revision="$2"; shift 2;;
    --name) box_name="$2"; destroy_server="no"; shift 2;;
    --no-destroy) destroy_server="no"; shift 2;;
    --) break;;
    *) echo "Unknown option $1"; exit 1;;
    esac
done

echo "Creating digitalocean image"
if [[ "${deploy_env}" == "staging" ]]; then
    assertNotEmpty DIGITAL_OCEAN_TOKEN_STAGING
    export DIGITAL_OCEAN_TOKEN="${DIGITAL_OCEAN_TOKEN_STAGING}"
elif [[ "${deploy_env}" == "dev" ]]; then
    assertNotEmpty DIGITAL_OCEAN_TOKEN_DEV
    export DIGITAL_OCEAN_TOKEN="${DIGITAL_OCEAN_TOKEN_DEV}"
elif [[ "${deploy_env}" == "prod" ]]; then
    assertNotEmpty DIGITAL_OCEAN_TOKEN_PROD
    export DIGITAL_OCEAN_TOKEN="${DIGITAL_OCEAN_TOKEN_PROD}"
else
    echo "No such env ${deploy_env}."
    exit 1
fi

vps="/bin/bash ${SCRIPT_DIR}/digitalocean.sh"

readonly ssh_keys="${HOME}/.ssh/id_rsa_caas_${deploy_env}"
readonly scp202="scp -P 202 -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}"
readonly scp22="scp -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}"

readonly ssh202="ssh -p 202 -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}"
readonly ssh22="ssh -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}"

if [[ ! -f "${ssh_keys}" ]]; then
    echo "caas ssh key is missing at ${ssh_keys} (pick it up from secrets repo)"
    exit 1
fi

function get_pretty_revision() {
    local git_rev="$1"
    local sha1=$(git rev-parse --short "${git_rev}" 2>/dev/null)

    echo "${sha1}"
}

now=$(date "+%Y-%m-%d-%H%M%S")
pretty_revision=$(get_pretty_revision "${revision}")

if [[ -z "${box_name}" ]]; then
    # if you change this, change the regexp is appstore/janitor.js
    box_name="box-${deploy_env}-${pretty_revision}-${now}" # remove slashes

    # create a new server if no name given
    if ! caas_ssh_key_id=$($vps get_ssh_key_id "caas"); then
        echo "Could not query caas ssh key"
        exit 1
    fi
    echo "Detected caas ssh key id: ${caas_ssh_key_id}"

    echo "Creating Server with name [${box_name}]"
    if ! server_id=$($vps create ${caas_ssh_key_id} ${box_name}); then
        echo "Failed to create server"
        exit 1
    fi
    echo "Created server with id: ${server_id}"

    # If we run scripts overenthusiastically without the wait, setup script randomly fails
    echo -n "Waiting 120 seconds for server creation"
    for i in $(seq 1 24); do
        echo -n "."
        sleep 5
    done
    echo ""
else
    if ! server_id=$($vps get_id "${box_name}"); then
        echo "Could not determine id from name"
        exit 1
    fi
    echo "Reusing server with id: ${server_id}"

    $vps power_on "${server_id}"
fi

# Query until we get an IP
while true; do
    echo "Trying to get the server IP"
    if server_ip=$($vps get_ip "${server_id}"); then
        echo "Server IP : [${server_ip}]"
        break
    fi
    echo "Timedout, trying again in 10 seconds"
    sleep 10
done

while true; do
    echo "Trying to copy init script to server"
    if $scp22 "${SCRIPT_DIR}/initializeBaseUbuntuImage.sh" root@${server_ip}:.; then
        break
    fi
    echo "Timedout, trying again in 30 seconds"
    sleep 30
done

echo "Copying infra_version.js"
$scp22 "${SCRIPT_DIR}/../src/infra_version.js" root@${server_ip}:.

echo "Copying box source"
cd "${SOURCE_DIR}"
git archive --format=tar HEAD | $ssh22 "root@${server_ip}" "cat - > /tmp/box.tar.gz"

echo "Executing init script"
if ! $ssh22 "root@${server_ip}" "/bin/bash /root/initializeBaseUbuntuImage.sh caas"; then
    echo "Init script failed"
    exit 1
fi

echo "Shutting down server with id : ${server_id}"
$ssh22 "root@${server_ip}" "shutdown -f now" || true # shutdown sometimes terminates ssh connection immediately making this command fail

# wait 10 secs for actual shutdown
echo "Waiting for 10 seconds for server to shutdown"
sleep 30

echo "Powering off server"
if ! $vps power_off "${server_id}"; then
    echo "Could not power off server"
    exit 1
fi

snapshot_name="box-${deploy_env}-${pretty_revision}-${now}"
echo "Snapshotting as ${snapshot_name}"
if ! image_id=$($vps snapshot "${server_id}" "${snapshot_name}"); then
    echo "Could not snapshot and get image id"
    exit 1
fi

if [[ "${destroy_server}" == "yes" ]]; then
    echo "Destroying server"
    if ! $vps destroy "${server_id}"; then
        echo "Could not destroy server"
        exit 1
    fi
else
    echo "Skipping server destroy"
fi

echo "Transferring image ${image_id} to other regions"
$vps transfer_image_to_all_regions "${image_id}"

echo "Done."
