#!/usr/bin/env bash

# Ensure this file is executable via `chmod a+x deken`, then place it
# somewhere on your $PATH, like ~/bin. The rest of Deken will self-install
# on first run into the ~/.deken/ directory.

# Much of this code is pilfered from Clojure's Leiningen tool

export DEKEN_VERSION="0.2.6"
export DEKEN_HOME="${DEKEN_HOME:-"$HOME/.deken"}"
DEKEN_GIT_BRANCH="${DEKEN_GIT_BRANCH:-master}"
DEKEN_BASE_URL="https://raw.githubusercontent.com/pure-data/deken/${DEKEN_GIT_BRANCH}/developer"

VIRTUALENV_VERSION="15.1.0"
VIRTUALENV_URL="https://pypi.io/packages/source/v/virtualenv/virtualenv-${VIRTUALENV_VERSION}.tar.gz"


error() {
    echo "$@" 1>&2
}

if [ $(id -u) -eq 0 ] && [ "$DEKEN_ROOT" = "" ]; then
    error "WARNING: You're currently running as root; probably by accident."
    error "Press control-C to abort or Enter to continue as root."
    error "Set DEKEN_ROOT to disable this warning."
    read _
fi

if [ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]; then
    delimiter=";"
else
    delimiter=":"
fi

if [ "$OSTYPE" = "cygwin" ]; then
  cygwin=true
else
  cygwin=false
fi

# allow the user to override the default python
if [ "x${PYTHON_BIN}" = x ]; then
 PYTHON_BIN=python
fi

# This needs to be defined before we call HTTP_CLIENT below
if [ "$HTTP_CLIENT" = "" ]; then
    if which curl >/dev/null; then
        if [ "$https_proxy" != "" ]; then
            CURL_PROXY="-x $https_proxy"
        fi
        HTTP_CLIENT="curl $CURL_PROXY -f -L -o"
    else
        HTTP_CLIENT="wget -O"
    fi
fi


if $cygwin; then
    export DEKEN_HOME=$(cygpath -w "$DEKEN_HOME")
fi

bail_install() {
    error "Self-installation of Deken failed."
    error "Please paste any errors in the bug tracker at https://github.com/pure-data/deken/issues"
    # remove all trace of our attempts to install.
    rm -rf $DEKEN_HOME;
    # bail from this script.
    exit 1;
}
bail_install_msg() {
    error "$@"
    bail_install
}

bail_requirements() {
    rm -f "${DEKEN_HOME}/requirements.txt"
    error "Installation of requirements failed."
    error "You probably should install the following packages first:"
    error " - 'python-dev'"
    error " - 'libffi-dev'"
    error " - 'libssl-dev'"
    error "You can run 'deken install' or 'deken upgrade' anytime to"
    error " re-install (or upgrade) your Deken installation"

    exit 1
}

install_virtualenv() {
	echo "Downloading & installing Virtualenv."
	rm -rf $DEKEN_HOME/virtualenv-source
	mkdir -p $DEKEN_HOME/virtualenv-source && \
	$HTTP_CLIENT $DEKEN_HOME/virtualenv.tar.gz "${VIRTUALENV_URL}" && \
	tar -zxvf $DEKEN_HOME/virtualenv.tar.gz -C $DEKEN_HOME/virtualenv-source/ && \
	mv $DEKEN_HOME/virtualenv-source/virtualenv-*/* $DEKEN_HOME/virtualenv-source
	[ -d "$DEKEN_HOME/virtualenv-source" ] && (\
		cd $DEKEN_HOME/virtualenv-source && \
		/usr/bin/env "${PYTHON_BIN}" setup.py build ) \
		|| bail_install;
}

install_deken() {
    which "${PYTHON_BIN}" >/dev/null || \
        bail_install_msg "Oops, no Python found! You need Python to run Deken: ${PYTHON_BIN}
You can specify an alternative Python interpreter via the PYTHON_BIN envvar"
    which make >/dev/null || \
        bail_install_msg "Oops, no Make found! You need Make to run Deken."
    error "This is your first time running deken on this machine."
    error "I'm going to install myself and my dependencies into ${DEKEN_HOME} now."
    error "Feel free to ctrl-C now if you don't want to do this."
    sleep 3;
    [ -d "$DEKEN_HOME" ] || mkdir -p $DEKEN_HOME;
    [ -e "$DEKEN_HOME/requirements.txt" ] || (\
        ( echo "Fetching Python requirements file: $DEKEN_BASE_URL/requirements.txt" && \
        $HTTP_CLIENT $DEKEN_HOME/requirements.txt $DEKEN_BASE_URL/requirements.txt ) || bail_install)
    [ -e "$DEKEN_HOME/requirements.txt" ] || bail_install
    [ -e "$DEKEN_HOME/deken.hy" ] || (\
        ( echo "Fetching main hylang file: $DEKEN_BASE_URL/deken.hy" && \
        $HTTP_CLIENT $DEKEN_HOME/deken.hy $DEKEN_BASE_URL/deken.hy ) || bail_install)
    [ -e "$DEKEN_HOME/deken.hy" ] || bail_install
    [ -x "$DEKEN_HOME/virtualenv-source/virtualenv.py" ] || install_virtualenv;
    [ -d "$DEKEN_HOME/virtualenv" ] || (\
        echo "Setting up the virtual environment." && \
        $DEKEN_HOME/virtualenv-source/virtualenv.py "$DEKEN_HOME/virtualenv" || exit 1)
    [ -x "$DEKEN_HOME/virtualenv/bin/hy" ] || (\
        echo "Installing deken library dependencies." && \
        $DEKEN_HOME/virtualenv/bin/pip install -r $DEKEN_HOME/requirements.txt || bail_requirements)
}

upgrade_deken() {
    # first upgrade this script itself
    echo "Upgrading $0."
    $HTTP_CLIENT $0 $DEKEN_BASE_URL/deken
    # next upgrade our dependencies
    for f in requirements.txt deken.hy;
    do
        echo "Fetching $f file: $DEKEN_BASE_URL/$f";
        $HTTP_CLIENT $DEKEN_HOME/.upgrade-$f $DEKEN_BASE_URL/$f || ( error "Error upgrading $f"; exit 1; );
        mv $DEKEN_HOME/.upgrade-$f $DEKEN_HOME/$f;
    done
    # finally update the python dependencies
    $DEKEN_HOME/virtualenv/bin/pip install -r $DEKEN_HOME/requirements.txt || bail_requirements
    echo "Successfully upgraded."
}

tryrun_deken() {
    if [ ! -x "$DEKEN_HOME/virtualenv/bin/hy" ]; then
       error "Unable to find '${DEKEN_HOME}/virtualenv/bin/hy'"
       error "Try running '$0 install' or '$0 upgrade'"
       exit 1
    fi
    if [ -e $DEKEN_HOME/deken.hy ]; then
       $DEKEN_HOME/virtualenv/bin/hy $DEKEN_HOME/deken.hy "$@"
    else
       error "Unable to find '${DEKEN_HOME}/deken.hy'"
       error "Try running '$0 install' or '$0 upgrade'"
       exit 1
    fi
}

# make sure we are deployed
[ -d "$DEKEN_HOME" ] || install_deken

# last check to make sure we can bootstrap
[ -d "$DEKEN_HOME" ] || bail_install;

# catch the special "upgrade" command
case "$1" in
  upgrade|update)
    # run the upgrade command instead
    upgrade_deken
    ;;
  install)
    install_deken
    ;;
  *)
    # run the real deken command with args passed through
    tryrun_deken "$@"
    ;;
esac
