#!/usr/bin/env bash

export DOKKU_ROOT=${DOKKU_ROOT:="/home/dokku"}
export PLUGIN_PATH=${PLUGIN_PATH:="/var/lib/dokku-alt/plugins"}

if [[ $(id -un) != "dokku" && $1 != "plugins-install" ]]; then
  sudo -u dokku -H NAME="$(id -un)" FINGERPRINT="shell" $0 "$@"
  exit
fi

# locale
export LANGUAGE=${LANGUAGE:-en_US.UTF-8}
export LANG=${LANG:-en_US.UTF-8}
export LC_ALL=${LC_ALL:-en_US.UTF-8}

source "$PLUGIN_PATH/dokku_common"

[[ -f $DOKKU_ROOT/dokkurc ]] && source $DOKKU_ROOT/dokkurc

if [[ "$1" == "" ]]; then
  dokku help
  exit
fi

: | pluginhook verify-command "$@"

case "$1" in
  release)
    verify_app_name "$2"
    verify_max_args "2" "$@"

    info "Releasing $APP ..."
    tag_image "$IMAGE_GENERIC:build" "$IMAGE_GENERIC:release"
    pluginhook pre-release "$APP"
    if is_image_buildstep_based "$IMAGE_GENERIC:release"; then
      : | pluginhook env-vars "$APP" | sed 's/^/export /g' | \
        docker run -i -a stdin "$IMAGE_GENERIC:release" \
        /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/app-env.sh" | \
        commit_image "$IMAGE_GENERIC:release"
    fi
    pluginhook post-release "$APP"
    ;;

  deploy)
    verify_app_name "$2"
    verify_max_args "3" "$@"

    TAG="${3:-release}"
    export IMAGE_TAG="$TAG"

    # prepare for deployment
    info "Deploying $APP ..."
    pluginhook pre-deploy "$APP"

    if [[ ! -f "$DOKKU_ROOT/$APP/DISABLED" ]]; then
      DOCKER_ARGS="$(: | pluginhook docker-args "$APP" web)"

      # verify preboot
      PREBOOT="$(: | pluginhook use-preboot "$APP" "$IMAGE")"

      if [[ "$PREBOOT" == "" ]]; then
        stop_and_remove_app_containers
      fi

      # start the app
      if is_image_buildstep_based "$IMAGE_GENERIC:$TAG"; then
        # buildstep
        INT_PORT="$APP_PORT"
        id=$(docker run --cidfile="$(get_cid_file_name app)" -d -p "$INT_PORT" -e PORT="$INT_PORT" --name="$(get_app_container_name app)" $DOCKER_ARGS "$IMAGE_GENERIC:$TAG" /start)
        addr=$(docker port $id "$INT_PORT")
        EXT_ADDR="${addr%:*}"
        EXT_PORT="${addr#*:}"
      else
        # Dockerfile
        EXT_PORT=""
        INT_PORT=""
        EXT_ADDR=""
        id=$(docker run --cidfile="$(get_cid_file_name app)" -d -P --env-file=<(: | pluginhook env-vars "$APP") --name="$(get_app_container_name app)" $DOCKER_ARGS "$IMAGE_GENERIC:$TAG")
        for test_port in 80 8080 "$APP_PORT"; do
          if addr=$(docker port $id "$test_port" 2>/dev/null); then
            INT_PORT="$test_port"
            EXT_ADDR="${addr%:*}"
            EXT_PORT="${addr#*:}"
          fi
        done
      fi

      if [[ "$EXT_PORT" == "" ]] || [[ "$INT_PORT" == "" ]]; then
        echo -n > "$DOKKU_ROOT/$APP/URL"
        verbose "No external HTTP port published"
        pluginhook post-deploy "$APP" ""
        info2 "Application deployed"
      else
        if [[ "$DOKKU_SUPPRESS_FIREWALL_WARNING" != "1" ]] && [[ "$EXT_ADDR" == "0.0.0.0" ]]; then
          verbose ''
          verbose 'WARNING: You use potentially insecure docker configuration which exposes all ports to outside world.'
          verbose 'Due to the way Docker works most of Firewall scripts will not block access to docker exposed ports.'
          verbose 'Consider adding DOCKER_OPTS="$DOCKER_OPTS --ip=127.0.0.1" to /etc/default/docker and restart docker service.'
          verbose ''
        fi

        if [[ "$PREBOOT" != "" ]]; then
          verbose "Running pre-flight checks..."
          if ! pluginhook check-preboot "$APP" "$id" "$EXT_PORT"
          then
            stop_and_remove_container "$id"
            fail "Application failed to deploy!"
          fi
        fi

        echo "http://$(< "$DOKKU_ROOT/HOSTNAME"):$EXT_PORT" > "$DOKKU_ROOT/$APP/URL"
        pluginhook post-deploy "$APP" "$EXT_PORT" "$INT_PORT"
        info2 "Application deployed:"
        verbose "$(dokku url $APP)"
      fi

      # save container ID
      echo "$id" > "$APP_NAME_FILE"

      if [[ "$TAG" != "latest" ]]; then
        tag_image "$IMAGE_GENERIC:$TAG" "$IMAGE_GENERIC:latest"
      fi

      if [[ "$PREBOOT" != "" ]]; then
        pluginhook post-preboot "$APP" "$id" || true
        stop_and_remove_app_containers "" "$id"
      fi
    else
      stop_and_remove_app_containers
      verbose "Application disabled - will not be run"
      pluginhook post-deploy "$APP" ""
      tag_image "$IMAGE_GENERIC:release" "$IMAGE_GENERIC:latest"
    fi
    ;;

  cleanup)
    info "Cleaning up ..."
    docker ps -a | grep -v " Up " | grep -v "seconds ago" | grep -v "_data" | awk '{print $1}' | xargs docker rm &> /dev/null || true
    docker images -a | grep '<none>' |  awk '{print $3}'  | xargs docker rmi &> /dev/null || true
    ;;

  plugins)
    ls -1 -d $PLUGIN_PATH/*/
    ;;

  plugins-install)
    [[ "$(id -un)" != "root" ]] && fail "Plugins install can be run only as root!"
    shift 1
    for script in $(ls -d $PLUGIN_PATH/*/install); do
      plugin="$(basename "$(dirname $script)")"
      echo "Installing $plugin..."
      $script "$@"
    done
    dokku deploy:all
    ;;

  # temporary hack for https://github.com/progrium/dokku/issues/82
  deploy:all)
    for app in $(ls -d $DOKKU_ROOT/*/ 2>/dev/null); do
      if [[ -f "$app/refs/heads/master" ]]; then
        dokku deploy "$(basename $app)" "latest" || true
      fi
    done
    wait
    ;;

  help)
    cat<<EOF | pluginhook commands help | sort | sed 's/\s\s\s*/|/2' | column -t -s '|'
    help             Print the list of commands
    plugins          Print active plugins
    plugins-install  Install active plugins
EOF
    ;;

  *:help)
    CATEGORY="$(echo "$1" | cut -d':' -f1):"
    dokku help | grep "^\s*$CATEGORY"
    ;;

  *)
    for script in $(ls -d $PLUGIN_PATH/*/commands 2>/dev/null); do
      $script "$@"
    done
    ;;

esac
