# /bin/bash - help gedit syntax highlight do the right thing
# autoenv script (https://github.com/kennethreitz/autoenv)
# Use ". .env -h" for help.
#
# This script is an autoenev script that either activates or creates
# a local virtualenv in '.venv' for (almost) any project. Typical
# project assets like 'setup.py' and requirements files are used to
# populate the virtualenv.
#
# This script is tested with bash, report problems with other shells to
#
#   https://github.com/Springerle/py-generic-project/issues
#
# It should work on any Linux, and Mac OSX.
#
_venv_virtualenv="/usr/bin/python2 -m virtualenv"
_venv_py3=true
_venv_pip_req='pip>18'
_venv_master_url="https://raw.githubusercontent.com/Springerle/py-generic-project/master/.env"

#_venv_temp=/usr/local/bin/virtualenv
#if test -x $_venv_temp; then
#    _venv_virtualenv=$_venv_temp
#fi
test "${_venv_py3:0:2}" != '{''{' || _venv_py3=true
if $_venv_py3; then # Python 3 mode?
    # /opt/pyenv, see https://github.com/jhermann/priscilla/tree/master/pyenv
    _venv_temp=/opt/pyenv/bin/python3
    if test -x $_venv_temp; then
        _venv_virtualenv="$_venv_temp -m venv"
    fi
    # python3 venv in recent Debian / Ubuntu
    # prefer a version that has Tkinter installed, if available
    _venv_py_tk=$(dpkg-query --show -f '${Version}' python3-tk 2>/dev/null | cut -f-2 -d.)
    for _venv_temp in $_venv_py_tk 3 3.7 3.6 3.5 3.4 3.3; do
        _venv_temp=/usr/bin/python$_venv_temp
        if test -x $_venv_temp; then
            _venv_virtualenv="$_venv_temp -m venv"
            break
        fi
    done
    unset _venv_py_tk
fi

_venv_readlink=readlink
case "$(uname -s)" in
    # See http://en.wikipedia.org/wiki/Uname#Examples
    Darwin)
        _venv_temp="/usr/local/opt/coreutils/libexec/gnubin/readlink"
        if test -x $_venv_temp; then
            _venv_readlink=$_venv_temp
        else
            echo "*** No readlink command, do a 'brew install coreutils'..."
            return 1
        fi
        ;;
    CYGWIN*)
        ;;
    Linux|*)
        ;;
esac

test -z "$JENKINS_URL" || echo '***' "\$0=$0" "\$BASH_SOURCE=${BASH_SOURCE[0]}"
if test "$0" = "-bash" -o "$(basename -- "$0")" = "bash" -o "$(basename -- "${BASH_SOURCE[0]}")" = ".env"; then
    _venv_script=$($_venv_readlink -f ${BASH_SOURCE[0]})
elif test "$(basename -- "$0")" = ".env"; then
    _venv_script=$($_venv_readlink -f "$0")
fi
_venv_script="${_venv_script:-/dont-know-really/.env}"
_venv_xtrace=$(set +o | grep xtrace)
set +x
_venv_name="$(basename $(pwd))"

_venv_pip_log() {
    if $_venv_verbose; then
        cat
    else
        egrep "Found.existing.installation|Collecting|Installing.collected.packages|Searching.for|Installed|Finished"
    fi
}

# command line flags, mostly for CI server usage
_venv_create=false
_venv_develop=false
_venv_verbose=false
while test "${1:0:1}" = "-"; do
    case "$1" in
        --yes) _venv_create=true ;;
        --develop) _venv_develop=true ;;
        --verbose | -v) _venv_verbose=true; set -x ;;
        --virtualenv) shift; _venv_virtualenv="$1" ;;
        --help | -h)
            #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            echo "usage: . $_venv_script <options>"
            echo
            echo "Create and/or activate a Python virtual environment. Updates pip and other"
            echo "system packages, and recognizes 'dev-requirements.txt' and 'setup.py' or"
            echo "'requirements.txt'."
            echo
            echo "This is an autoenv script (see https://github.com/kennethreitz/autoenv)."
            echo
            echo "Options:"
            echo "    --yes                 create missing venv without prompting"
            echo "    --develop             call 'develop -U' on activation"
            echo "    -v | --verbose        don't filter install logs on terminal"
            echo "                          (full logs in '.venv/pip-install.log')"
            echo "    -h | --help           this help message"
            echo "    --virtualenv PATH     set explicit path of virtualenv binary to use"
            echo "    --update              update to the newest master copy"
            return 1
            ;;
        --update)
            python <<EOF
if 1:
                try:
                    from urllib.request import urlopen
                except ImportError:
                    from urllib2 import urlopen
                open('/tmp/$USER-py-env-update.py', 'wb').write(urlopen('$_venv_master_url').read())
EOF
            grep "unset _venv_xtrace" "/tmp/$USER-py-env-update.py" >/dev/null || return 1
            sed -r -e "s/^_venv_py3=.*/_venv_py3=$_venv_py3/" <"/tmp/$USER-py-env-update.py" >.env
            git diff .env || :
            echo ".env script update OK"
            return 0
            ;;
        *) echo "WARNING: Ignored unknown option '$1'" ;;
    esac
    shift
done

# Outside the tree of the .env script?
if pwd -P | egrep -v '^'$(dirname "$_venv_script")'($|/)' >/dev/null; then
    : echo Outside "[$0 $1 ; $_venv_script]"

# Inside the tree of the .env script, but have another local '.env'?
elif test \! -f .env -o "$_venv_script" != "$(pwd -P)/.env"; then
    : echo Inside "[$0 $1 ; $_venv_script]"

# Only try virtualenv creation outside of template dirs; the egrep pattern is escaped for hiding it from Jinja2
elif pwd -P | egrep -v '/{''{''.*''}''}(/|$)' >/dev/null || $_venv_create; then
    test -f ".env" && _venv_ask=true || _venv_ask=false

    # Look for existing venv at common locations
    for _venv_base in .venv venv . ..; do
        if test -f "$_venv_base/$_venv_name/bin/activate"; then
            deactivate 2>/dev/null || :
            . "$_venv_base/$_venv_name/bin/activate"
            if test -f setup.py; then
                $_venv_develop && python setup.py -q develop -U || :
                python setup.py --name --version --url | tr \\n \\0 \
                    | xargs -0 printf "*** Activated %s %s @ %s\\n" || :
            else
                echo "*** Activated $_venv_base/$_venv_name"
            fi
            _venv_ask=false
            break
        fi
    done

    if $_venv_ask && test \! -d .venv; then
        $_venv_create || { read -p "No virtualenv found, shall I create one for you? [Y/n] " -n 1 -r || REPLY='n'; echo; }
        if $_venv_create || echo "$REPLY" | egrep '^[Yy]?$' >/dev/null; then
            # Create, activate, and update virtualenv
            echo "Calling: $_venv_virtualenv .venv/$_venv_name"
            eval $_venv_virtualenv ".venv/$_venv_name"
            . ".venv/$_venv_name/bin/activate"
            ".venv/$_venv_name/bin/python" -m pip --log ".venv/install-pip.log" install -U "$_venv_pip_req" 2>&1 | _venv_pip_log \
                || echo >&2 "!!! WARN: pip -U pip failed (RC=$?), see .venv/install-pip.log for details"
            ".venv/$_venv_name/bin/python" -m pip --log ".venv/install-tools.log" install -U "setuptools>40" "wheel>0.30" 2>&1 | _venv_pip_log \
                || echo >&2 "!!! WARN: pip -U setuptools wheel failed (RC=$?), see .venv/install-tools.log for details"

            # Get rid of cruft some older systems produce
            ".venv/$_venv_name/bin/python" -m pip --log ".venv/uninstall-distribute.log" uninstall --yes distribute >/dev/null 2>&1 || :

            # pypandoc fails when the base package is missing, so we install it here, if possible
            if which pandoc >/dev/null ; then
                ".venv/$_venv_name/bin/python" -m pip --log ".venv/install-pandoc.log" install pypandoc 2>&1 | _venv_pip_log \
                    || echo >&2 "!!! WARN: pip install pypandoc failed (RC=$?), see .venv/install-pandoc.log for details"
            fi

            # Install development + project dependencies
            if test -f dev-requirements.txt; then
                ".venv/$_venv_name/bin/python" -m pip --log ".venv/pip-install-dev.log" install -r dev-requirements.txt 2>&1 | _venv_pip_log \
                    || echo >&2 "!!! WARN: pip install dev-requirements failed (RC=$?), see .venv/pip-install-dev.log for details"
            fi
            if test -f setup.py; then
                if grep "^# mkvenv: no-deps" "setup.py" >/dev/null; then
                    echo "*** Not installing setup.py packages as requested"
                else
                    ".venv/$_venv_name/bin/python" setup.py develop -U 2>&1 | _venv_pip_log
                fi
                echo
                ".venv/$_venv_name/bin/python" setup.py --name --version --author --author-email --license --description --url \
                    | tr \\n \\0 | xargs -0 printf "%s %s by %s <%s> [%s]\\n%s\\n%s\\n" || :
            else
                echo
                if test -f requirements.txt; then
                    echo "*** No 'setup.py' found, installing requirements..."
                    ".venv/$_venv_name/bin/python" -m pip --log ".venv/pip-install-req.log" install -r requirements.txt 2>&1 | _venv_pip_log
                else
                    echo "*** No 'setup.py' or 'requirements.txt' found, all done."
                fi
            fi
        else
            # prevent constant prompting
            mkdir -p .venv
        fi
    fi
fi

unset _venv_script _venv_name _venv_ask _venv_create _venv_develop _venv_pip_log _venv_base _venv_py_tk
unset _venv_readlink _venv_temp _venv_virtualenv _venv_verbose _venv_py3 _venv_pip_req _venv_master_url
eval $_venv_xtrace # restore xtrace state
unset _venv_xtrace
