#!/usr/bin/env bash

export PYTHON="${PYTHON:-python3}"
export VENV="_python"
export NODEENV="_node"
export PATH="$PWD/$VENV/bin:$PWD/node_modules/.bin:$PWD/$NODEENV/bin:$PATH"
export PREFIX="_site"

export GIT_REMOTE="origin"
export MASTER_BRANCH_REMOTE="master"

NODE_VERSION="14.2.0"

venv_setup() { # filename [force | silent]
    MD5_FILE="$VENV/$1.md5"

    if [ "_$2" = '_force' ] && [ -e "$MD5_FILE" ]; then
        rm "$MD5_FILE"
    fi

    if [ ! -d "$VENV" ]; then
        $PYTHON -m venv "$VENV" || exit 1
        $PYTHON -m pip install wheel
    fi

    if [ -e "$MD5_FILE" ] && md5sum -c "$MD5_FILE" > /dev/null 2>&1; then
        [ "_$2" != "_silent" ] && echo "Skipping full virtual environment update (no changes in $1)"
        if grep -q '# dynamic$' "$1"; then
            awk '/# dynamic$/{print $1}' "$1" |
                xargs $PYTHON -m pip install -U | \
                grep -v "skipping upgrade"
        fi
        return 0
    fi

    $PYTHON -m pip install -U -r "$1" | grep -v "skipping upgrade" || exit 1

    md5sum "$1" > "$MD5_FILE"
}

node_setup() { # [full | silent]
    MD5_FILE="$NODEENV/package.json.md5"

    if [ "_$2" = '_full' ] && [ -e "$MD5_FILE" ]; then
        rm "$MD5_FILE"
    fi

    if [ ! -d "$NODEENV" ] || [ "$(node -v)" != "v$NODE_VERSION" ]; then
        nodeenv --force -n "$NODE_VERSION" "$NODEENV" || exit 1
    fi

    if [ -e "$MD5_FILE" ] && md5sum -c "$MD5_FILE" > /dev/null 2>&1; then
        [ "_$2" != "_silent" ] && echo "Skipping virtual environment update (no changes in package.json)"
        patch-package --patch-dir src/js/patches
        return 0
    fi

    npm install --unsafe-perms || exit 1
    [ -e "$PWD/node_modules/.cache" ] && rm -rf "$PWD/node_modules/.cache"

    md5sum "package.json" "package-lock.json" > "$MD5_FILE"
}

if [ ! -d "$VENV" ] && [ "_$1" != "_venv" ]; then
    echo "Setting up Python virtual environment: $VENV"
    venv_setup requirements.txt
fi

require_node() {
    if [ ! -d "$NODEENV" ]; then
        echo "Setting up Node.js virtual environment: $VENV"
        node_setup
    fi
}

repo() {
    $PYTHON -m src.utils.repo "$@"
}

case $1 in
    venv)
        case $2 in
            update)
                venv_setup requirements.txt $3

                if [ -e "$VENV/cli-requirements.txt.md5" ]; then
                    venv_setup cli-requirements.txt $3
                fi

                if [ -d "$NODEENV" ]; then
                    node_setup
                fi

                ;;
            remove) rm -rf "$VENV" "$NODEENV" "node_modules" ;;
            *) echo "Usage: $0 $1 update|remove [full]" ;;
        esac ;;

    repo) shift ;&
    pages|data) repo "$@" ;;

    pull)
        if [ "$(git status --porcelain=v1 | wc -l)" -eq 0 ]; then
            echo "Updating ./"
            git pull -q --rebase "$GIT_REMOTE" "$MASTER_BRANCH_REMOTE"
        else
            echo "Not updating ./ due to uncommitted changes"
        fi

        repo pull ;;

    build)
        require_node
        ./bsu webpack ;&
    generate)
        shift
        $PYTHON -m src.utils.generate "$@" ;;

    debug)
        export HMR=1 DEBUG=1 ;&
    serve)
        require_node
        shift
        $PYTHON -m src.utils.serve "$@" ;;
    api)
        export FLASK_APP=src.utils.apiserver FLASK_DEBUG=1
        flask run ;;

    download-chats) $PYTHON -m src.utils.chats ;;
    sh|bash) "$@" ;;
    cli)
        shift
        venv_setup cli-requirements.txt silent
        $PYTHON -m src.utils.cli "$@" ;;
    repl) $PYTHON -i -m src.utils.repl ;;
    script) shift; module=$1; shift; $PYTHON -m src.scripts.$module "$@" ;;
    python) shift; $PYTHON $@ ;;
    pip) shift; $PYTHON -m pip $@ ;;
    npm|npx|node|webpack)
        require_node
        "$@"
        ;;
    *) echo "Usage: $0 venv|pages|pull|build|serve|react|download-chats|sh|bash|repl|script|python|pip|npm" ;;
esac
