#!/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

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_PORT="${addr#*:}"
      else
        # Dockerfile
        EXT_PORT=""
        INT_PORT=""
        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_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 [[ "$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
