#!/usr/bin/env bash
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/checks/functions"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
source "$PLUGIN_AVAILABLE_PATH/scheduler-docker-local/internal-functions"

trigger-scheduler-docker-local-scheduler-deploy() {
  declare desc="deploys an image tag for a given application"
  declare trigger="scheduler-deploy"
  declare DOKKU_SCHEDULER="$1" APP="$2" IMAGE_TAG="$3"

  if [[ "$DOKKU_SCHEDULER" != "docker-local" ]]; then
    return
  fi

  rm -f "${DOKKU_LIB_ROOT}/data/scheduler-docker-local/$APP/failed-containers"

  local DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$APP --label=com.dokku.container-type=deploy"
  local DOKKU_DOCKER_STOP_TIMEOUT DOKKU_HEROKUISH DOKKU_NETWORK_BIND_ALL IMAGE
  DOKKU_HEROKUISH=false
  DOKKU_CNB=false
  IMAGE="$(get_deploying_app_image_name "$APP" "$IMAGE_TAG")"

  is_image_cnb_based "$IMAGE" && DOKKU_CNB=true
  is_image_herokuish_based "$IMAGE" "$APP" && DOKKU_HEROKUISH=true
  local IMAGE_SOURCE_TYPE="dockerfile"
  [[ "$DOKKU_HEROKUISH" == "true" ]] && IMAGE_SOURCE_TYPE="herokuish"
  [[ "$DOKKU_CNB" == "true" ]] && IMAGE_SOURCE_TYPE="pack"
  local oldids=$(get_app_container_ids "$APP")

  DOKKU_NETWORK_BIND_ALL="$(plugn trigger network-get-property "$APP" bind-all-interfaces)"
  DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)"
  [[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}"

  DOKKU_START_CMD="$(config_get "$APP" DOKKU_START_CMD || true)"

  if [[ -z "$DOKKU_WAIT_TO_RETIRE" ]]; then
    local DOKKU_APP_DOKKU_WAIT_TO_RETIRE=$(config_get "$APP" DOKKU_WAIT_TO_RETIRE || true)
    local DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE=$(config_get --global DOKKU_WAIT_TO_RETIRE || true)
    local DOKKU_WAIT_TO_RETIRE=${DOKKU_APP_DOKKU_WAIT_TO_RETIRE:="$DOKKU_GLOBAL_DOKKU_WAIT_TO_RETIRE"}
  fi

  local WAIT="${DOKKU_WAIT_TO_RETIRE:-60}"

  local line
  local PROC_TYPE
  local PROC_COUNT
  local CONTAINER_INDEX
  while read -r line || [[ -n "$line" ]]; do
    PROC_TYPE=${line%%=*}
    PROC_COUNT=${line#*=}

    dokku_log_info1 "Deploying $PROC_TYPE (count=$PROC_COUNT)"
    export DOKKU_NETWORK_BIND_ALL="$DOKKU_NETWORK_BIND_ALL"
    export DOKKU_HEROKUISH="$DOKKU_HEROKUISH"
    export DOKKU_CNB="$DOKKU_CNB"
    export DOCKER_RUN_LABEL_ARGS="$DOCKER_RUN_LABEL_ARGS"
    export DOKKU_START_CMD="$DOKKU_START_CMD"
    export DOCKER_STOP_TIME_ARG="$DOCKER_STOP_TIME_ARG"
    "$PLUGIN_AVAILABLE_PATH/scheduler-docker-local/bin/scheduler-deploy-process" "$APP" "$IMAGE_SOURCE_TYPE" "$IMAGE" "$IMAGE_TAG" "$PROC_TYPE" "$PROC_COUNT"
  done < <(plugn trigger ps-current-scale "$APP")

  dokku_log_info1 "Running post-deploy"
  plugn trigger core-post-deploy "$APP" "$port" "$ipaddr" "$IMAGE_TAG"
  plugn trigger post-deploy "$APP" "$port" "$ipaddr" "$IMAGE_TAG"

  # kill the old container
  if [[ -n "$oldids" ]]; then
    # Let the old container finish processing requests, before terminating it
    dokku_log_info1 "Shutting down old containers in $WAIT seconds"
    (
      exec >/dev/null 2>/dev/null </dev/null
      trap '' INT HUP
      sleep "$WAIT"
      for oldid in $oldids; do
        if ! docker container inspect "$oldid" >/dev/null 2>&1; then
          continue
        fi
        # Disable the container restart policy
        "$DOCKER_BIN" container update --restart=no "$oldid" &>/dev/null || true

        # Attempt to stop, if that fails, then force a kill as docker seems
        # to not send SIGKILL as the docs would indicate. If that fails, move
        # on to the next.
        # shellcheck disable=SC2086
        "$DOCKER_BIN" container stop $DOCKER_STOP_TIME_ARG "$oldid" \
          || "$DOCKER_BIN" container kill "$oldid" \
          || plugn trigger retire-container-failed "$APP" "$oldid" # plugin trigger for event logging
      done
    ) &
    disown -a
    # Use trap since disown/nohup don't seem to keep child alive
    # Give child process just enough time to set the traps
    sleep 0.1
  fi
}

trigger-scheduler-docker-local-scheduler-deploy "$@"
