#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$(dirname $0)/../common/functions"

case "$1" in
  build)
    APP="$2"; IMAGE="dokku/$APP"; IMAGE_SOURCE_TYPE="$3"; TMP_WORK_DIR="$4"
    CACHE_DIR="$DOKKU_ROOT/$APP/cache"

    [[ -f "$DOKKU_ROOT/$APP/ENV" ]] && source "$DOKKU_ROOT/$APP/ENV"
    pushd "$TMP_WORK_DIR" &> /dev/null

    case "$IMAGE_SOURCE_TYPE" in
      buildstep)
        id=$(tar -c . | docker run -i -a stdin $DOKKU_IMAGE /bin/bash -c "mkdir -p /app && tar -xC /app")
        test "$(docker wait $id)" -eq 0
        docker commit $id $IMAGE > /dev/null
        [[ -d $CACHE_DIR ]] || mkdir $CACHE_DIR
        # *DEPRECATED* in v0.4.0: `pluginhook pre-build` will be removed in future releases
        pluginhook pre-build "$APP"
        pluginhook pre-build-buildstep "$APP"

        # *DEPRECATED* in v0.3.14: `pluginhook docker-args` will be removed in future releases
        # https://github.com/progrium/dokku/issues/896 & https://github.com/progrium/dokku/issues/906
        DOCKER_ARGS=$(: | pluginhook docker-args $APP build)
        DOCKER_ARGS+=$(: | pluginhook docker-args-build $APP)
        id=$(docker run -d -v $CACHE_DIR:/cache -e CACHE_PATH=/cache $DOCKER_ARGS $IMAGE /build/builder)
        docker attach $id
        test "$(docker wait $id)" -eq 0
        docker commit $id $IMAGE > /dev/null

        # *DEPRECATED* in v0.4.0: `pluginhook post-build` will be removed in future releases
        pluginhook post-build "$APP"
        pluginhook post-build-buildstep "$APP"
        ;;

      dockerfile)
        # extract first port from Dockerfile
        DOCKERFILE_PORT=$(grep EXPOSE Dockerfile | head -1 | awk '{ print $2 }' || true)
        [[ -n "$DOCKERFILE_PORT" ]] && dokku config:set-norestart $APP DOKKU_DOCKERFILE_PORT=$DOCKERFILE_PORT

        # buildstep pluginhooks don't necessarily make sense for dockerfiles. call the new breed!!!
        pluginhook pre-build-dockerfile "$APP"

        [[ "$DOKKU_DOCKERFILE_CACHE_BUILD" == "false" ]] && DOKKU_DOCKER_BUILD_OPTS="$DOKKU_DOCKER_BUILD_OPTS --no-cache"
        docker build $DOKKU_DOCKER_BUILD_OPTS -t "$IMAGE" .

        pluginhook post-build-dockerfile "$APP"
        ;;

      *)
        dokku_log_fail "Building image source type $IMAGE_SOURCE_TYPE not supported!"
        ;;
    esac
    ;;

  release)
    APP="$2"; IMAGE="dokku/$APP"; IMAGE_SOURCE_TYPE="$3"
    case "$IMAGE_SOURCE_TYPE" in
      buildstep)
        # *DEPRECATED* in v0.4.0: `pluginhook pre-release` will be removed in future releases
        pluginhook pre-release "$APP"
        pluginhook pre-release-buildstep "$APP"
        if [[ -f "$DOKKU_ROOT/ENV" ]]; then
          id=$(docker run -i -a stdin $IMAGE /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/00-global-env.sh" < "$DOKKU_ROOT/ENV")
          test "$(docker wait $id)" -eq 0
          docker commit $id $IMAGE > /dev/null
        fi
        if [[ -f "$DOKKU_ROOT/$APP/ENV" ]]; then
          id=$(docker run -i -a stdin $IMAGE /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/01-app-env.sh" < "$DOKKU_ROOT/$APP/ENV")
          test "$(docker wait $id)" -eq 0
          docker commit $id $IMAGE > /dev/null
        fi
        # *DEPRECATED* in v0.4.0: `pluginhook post-release` will be removed in future releases
        pluginhook post-release "$APP"
        pluginhook post-release-buildstep "$APP"
        ;;

      dockerfile)
        # buildstep pluginhooks don't necessarily make sense for dockerfiles. call the new breed!!!
        pluginhook pre-release-dockerfile "$APP"
        pluginhook post-release-dockerfile "$APP"
        ;;

      *)
        dokku_log_fail "Releasing image source type $IMAGE_SOURCE_TYPE not supported!"
        ;;
    esac
    ;;

  trace)
    [[ -d $DOKKU_ROOT/.dokkurc ]] || mkdir -p $DOKKU_ROOT/.dokkurc
    [[ "$2" == "on" ]] || [[ "$2" == "off" ]] || {
      echo "Valid trace options are [on/off]"
      exit 1
    }

    if [[ "$2" == "on" ]]; then
      echo "Enabling dokku trace"
      echo "export DOKKU_TRACE=1" > $DOKKU_ROOT/.dokkurc/DOKKU_TRACE
    fi

    if [[ "$2" == "off" ]]; then
      echo "Disabling dokku trace"
      rm -f $DOKKU_ROOT/.dokkurc/DOKKU_TRACE
    fi
    ;;

  delete)
    dokku apps:destroy $2
    ;;

  ls)
    dokku_apps=$(ls -d $DOKKU_ROOT/*/ 2>/dev/null) || (echo "You haven't deployed any applications yet" && exit 1)

    dokku_col_log_info1_quiet "App Name" "Container Type" "Container Id" "Status"

    for dokku_app in $dokku_apps; do
      APP=$(basename $dokku_app)
      DOKKU_APP_CIDS=$(get_container_ids $APP)
      DOCKER_RUNNING_CONTAINERS=$(docker ps -q --no-trunc)
      if [[ -n $DOKKU_APP_CIDS ]]; then
        for DOKKU_APP_CID in $DOKKU_APP_CIDS; do
          DOKKU_APP_CONTAINER_STATUS="stopped"
          [[ $DOCKER_RUNNING_CONTAINERS =~ $DOKKU_APP_CID ]] && DOKKU_APP_CONTAINER_STATUS="running"
          DOKKU_APP_CONTAINER_TYPE=$(grep -l $DOKKU_APP_CID $DOKKU_ROOT/$APP/CONTAINER.* | awk -F. '{ print $2 }')
          dokku_col_log_msg "$APP" "$DOKKU_APP_CONTAINER_TYPE" "${DOKKU_APP_CID:0:12}" "$DOKKU_APP_CONTAINER_STATUS"
        done
      else
        dokku_col_log_msg "$APP" "NOT_DEPLOYED" "NOT_DEPLOYED" "NOT_DEPLOYED"
      fi
    done
    ;;

  logs)
    [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
    verify_app_name "$2"
    APP="$2";

    if (is_deployed $APP); then
      CONTAINER_IDS=( $(get_container_ids $APP) )
      LAST_CONTAINER_ID=${CONTAINER_IDS[${#CONTAINER_IDS[@]} - 1]}

      if [[ $3 == "-t" ]]; then
        DOKKU_LOGS_ARGS="--follow"
      else
        DOKKU_LOGS_ARGS="--tail 100"
      fi
      for CID in "${CONTAINER_IDS[@]}";do
        if [[ "$CID" != "$LAST_CONTAINER_ID" ]];then
          DOKKU_LOGS_CMD+="docker logs $DOKKU_LOGS_ARGS $CID& "
        else
          DOKKU_LOGS_CMD+="docker logs $DOKKU_LOGS_ARGS $CID; "
        fi
      done
      bash -c "($DOKKU_LOGS_CMD)"
    else
      echo "Application's container not found"
    fi
    ;;

  run)
    [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
    verify_app_name "$2"
    APP="$2"; IMAGE="dokku/$APP"

    shift 2

    DOCKER_ARGS=$(: | pluginhook docker-args $APP run)
    DOCKER_ARGS+=$(: | pluginhook docker-args-run $APP)
    [[ $DOKKU_RM_CONTAINER ]] && DOKKU_RUN_OPTS="--rm"
    has_tty && DOKKU_RUN_OPTS+=" -i -t"
    is_image_buildstep_based "$IMAGE" && EXEC_CMD="/exec"

    docker run $DOKKU_RUN_OPTS $DOCKER_ARGS $IMAGE $EXEC_CMD "$@"
    ;;

  url | urls)
    [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
    verify_app_name "$2"
    APP="$2";

    if [[ -s "$DOKKU_ROOT/$APP/URLS" ]]; then
      case "$1" in
        url)
          grep "^http" "$DOKKU_ROOT/$APP/URLS" | head -1
        ;;
        urls)
          grep "^http" "$DOKKU_ROOT/$APP/URLS"
        ;;
      esac

      exit 0
    fi

    SCHEME="http"; SSL="$DOKKU_ROOT/$APP/tls"; WILDCARD_SSL="$DOKKU_ROOT/tls"
    if [[ -e "$SSL/server.crt" && -e "$SSL/server.key" ]] || [[ -e "$WILDCARD_SSL/server.crt" && -e "$WILDCARD_SSL/server.key" ]]; then
      SCHEME="https"
    fi

    if [[ -f "$DOKKU_ROOT/VHOST" ]]; then
      echo "$SCHEME://$(< "$DOKKU_ROOT/VHOST")"
    else
      for PORT_FILE in $DOKKU_ROOT/$APP/PORT.*; do
        echo "$SCHEME://$(< "$DOKKU_ROOT/HOSTNAME"):$(< "$PORT_FILE")"
      done
    fi
  ;;

  version)
    cat "$DOKKU_ROOT/VERSION" || {
      echo "Unable to determine dokku's version" 2>&1
      exit 1
    }
    ;;

  help)
    cat && cat<<EOF
    ls                                              Pretty listing of deployed applications and containers
    logs <app> [-t]                                 Show the last logs for an application (-t follows)
    run <app> <cmd>                                 Run a command in the environment of an application
    url <app>                                       Show the first URL for an application (compatibility)
    urls <app>                                      Show all URLs for an application
    version                                         Print dokku's version
EOF
    ;;

  *)
    exit $DOKKU_NOT_IMPLEMENTED_EXIT
    ;;

esac
