#!/usr/bin/env bash
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config"
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions"
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
if [[ -f "$PLUGIN_AVAILABLE_PATH/docker-options/functions" ]]; then
  source "$PLUGIN_AVAILABLE_PATH/docker-options/functions"
fi

service_connect() {
  local SERVICE="$1"
  local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
  local SERVICE_NAME="$(get_service_name "$SERVICE")"
  local DATABASE_NAME="$(get_database_name "$SERVICE")"

  dokku_log_fail "Not yet implemented"
}

service_create() {
  local SERVICE="$1"
  is_valid_service_name "$SERVICE" || dokku_log_fail "Please specify a valid name for the service. Valid characters are: [A-Za-z0-9_]+"
  [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service"
  [[ ! -d "$PLUGIN_DATA_ROOT/$SERVICE" ]] || dokku_log_fail "$PLUGIN_SERVICE service $SERVICE already exists"
  SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
  LINKS_FILE="$SERVICE_ROOT/LINKS"

  service_parse_args "${@:2}"

  if ! service_image_exists "$SERVICE"; then
    if [[ "$PLUGIN_DISABLE_PULL" == "true" ]]; then
      dokku_log_warn "${PLUGIN_DISABLE_PULL_VARIABLE} environment variable detected. Not running pull command." 1>&2
      dokku_log_warn "   docker image pull ${IMAGE}" 1>&2
      dokku_log_warn "$PLUGIN_SERVICE service creation failed"
      exit 1
    fi
    "$DOCKER_BIN" image pull "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" || dokku_log_fail "$PLUGIN_SERVICE image $PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION pull failed"
  fi

  plugn trigger service-action pre-create "$PLUGIN_COMMAND_PREFIX" "$SERVICE"
  mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory"
  mkdir -p "$SERVICE_ROOT/data" || dokku_log_fail "Unable to create service data directory"
  mkdir -p "$SERVICE_ROOT/$PLUGIN_CONFIG_SUFFIX" || dokku_log_fail "Unable to create service config directory"
  touch "$LINKS_FILE"

  service_commit_config "$SERVICE"
  write_database_name "$SERVICE"
  plugn trigger service-action post-create "$PLUGIN_COMMAND_PREFIX" "$SERVICE"
  service_create_container "$SERVICE"
  plugn trigger service-action post-create-complete "$PLUGIN_COMMAND_PREFIX" "$SERVICE"
}

service_create_container() {
  local SERVICE="$1"
  local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
  local SERVICE_HOST_ROOT="$PLUGIN_DATA_HOST_ROOT/$SERVICE"
  local SERVICE_NAME="$(get_service_name "$SERVICE")"
  local DATABASE_NAME="$(get_database_name "$SERVICE")"

  if [[ -f "$SERVICE_ROOT/CONFIG_OPTIONS" ]]; then
    export CONFIG_OPTIONS="$(cat "$SERVICE_ROOT/CONFIG_OPTIONS")"
  fi

  local network_alias="$(service_dns_hostname "$SERVICE")"

  rm -f "$SERVICE_ROOT/ID"
  declare -a DOCKER_ARGS
  DOCKER_ARGS=()
  DOCKER_ARGS+=("--cidfile=$SERVICE_ROOT/ID")
  DOCKER_ARGS+=("--env-file=$SERVICE_ROOT/ENV")
  DOCKER_ARGS+=("--hostname=$SERVICE_NAME")
  DOCKER_ARGS+=("--label=dokku.service=$PLUGIN_COMMAND_PREFIX")
  DOCKER_ARGS+=("--label=dokku=service")
  DOCKER_ARGS+=("--name=$SERVICE_NAME")
  DOCKER_ARGS+=("--restart=always")
  DOCKER_ARGS+=("--volume=$SERVICE_HOST_ROOT/data:/data")

  declare -a LINK_CONTAINER_DOCKER_ARGS
  LINK_CONTAINER_DOCKER_ARGS=()
  LINK_CONTAINER_DOCKER_ARGS+=("--rm")
  LINK_CONTAINER_DOCKER_ARGS+=("--link")
  LINK_CONTAINER_DOCKER_ARGS+=("$SERVICE_NAME:$network_alias")

  [[ -f "$SERVICE_ROOT/SERVICE_MEMORY" ]] && SERVICE_MEMORY="$(cat "$SERVICE_ROOT/SERVICE_MEMORY")"
  if [[ -n "$SERVICE_MEMORY" ]]; then
    DOCKER_ARGS+=("--memory=${SERVICE_MEMORY}m")
  fi

  [[ -f "$SERVICE_ROOT/SHM_SIZE" ]] && SERVICE_SHM_SIZE="$(cat "$SERVICE_ROOT/SHM_SIZE")"
  if [[ -n "$SERVICE_SHM_SIZE" ]]; then
    DOCKER_ARGS+=("--shm-size=${SERVICE_SHM_SIZE}")
  fi

  [[ -f "$SERVICE_ROOT/IMAGE" ]] && PLUGIN_IMAGE="$(cat "$SERVICE_ROOT/IMAGE")"
  [[ -f "$SERVICE_ROOT/IMAGE_VERSION" ]] && PLUGIN_IMAGE_VERSION="$(cat "$SERVICE_ROOT/IMAGE_VERSION")"

  local network="$(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "initial-network")"
  if [[ -n "$network" ]]; then
    DOCKER_ARGS+=("--network=${network}")
    DOCKER_ARGS+=("--network-alias=${network_alias}")
    LINK_CONTAINER_DOCKER_ARGS+=("--network=${network}")
  fi

  # shellcheck disable=SC2086
  suppress_output "$DOCKER_BIN" container create "${DOCKER_ARGS[@]}" "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" $CONFIG_OPTIONS

  if [[ -n "$(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-create-network")" ]]; then
    dokku_log_verbose_quiet "Connecting to networks after container create"
    while read -r line || [[ -n "$line" ]]; do
      dokku_log_verbose_quiet "- $line"
      "$DOCKER_BIN" network connect --alias "$network_alias" "$line" "$SERVICE_NAME"
    done < <(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-create-network" | tr "," "\n")
  fi
  suppress_output "$DOCKER_BIN" container start "$(cat "$SERVICE_ROOT/ID")"
  service_port_reconcile_status "$SERVICE"

  if [[ -n "$(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-start-network")" ]]; then
    dokku_log_verbose_quiet "Connecting to networks after container start"
    while read -r line || [[ -n "$line" ]]; do
      dokku_log_verbose_quiet "- $line"
      "$DOCKER_BIN" network connect --alias "$network_alias" "$line" "$SERVICE_NAME"
    done < <(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-start-network" | tr "," "\n")
  fi

  dokku_log_verbose_quiet "Waiting for container to be ready"
  if ! suppress_output "$DOCKER_BIN" container run "${LINK_CONTAINER_DOCKER_ARGS[@]}" "$PLUGIN_WAIT_IMAGE" -c "$network_alias:$PLUGIN_DATASTORE_WAIT_PORT"; then
    dokku_log_info2_quiet "Start of $SERVICE container output"
    dokku_container_log_verbose_quiet "$SERVICE_NAME"
    dokku_log_info2_quiet "End of $SERVICE container output"
    return 1
  fi

  dokku_log_info2 "$PLUGIN_SERVICE container created: $SERVICE"
  service_info "$SERVICE"
}

service_export() {
  local SERVICE="$1"
  local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
  local DATABASE_NAME="$(get_database_name "$SERVICE")"

  dokku_log_fail "Not yet implemented"
}

service_import() {
  local SERVICE="$1"
  local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
  local SERVICE_HOST_ROOT="$PLUGIN_DATA_HOST_ROOT/$SERVICE"
  local SERVICE_NAME="$(get_service_name "$SERVICE")"
  local DATABASE_NAME="$(get_database_name "$SERVICE")"

  dokku_log_fail "Not yet implemented"
}

service_start() {
  local SERVICE="$1"
  local QUIET="$2"
  local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
  local SERVICE_NAME="$(get_service_name "$SERVICE")"
  local ID=$("$DOCKER_BIN" container ps -aq --no-trunc --filter "status=running" --filter "name=^/$SERVICE_NAME$") || true
  if [[ -n $ID ]]; then
    [[ -z $QUIET ]] && dokku_log_warn "Service is already started"
    if [[ ! -f "$SERVICE_ROOT/ID" ]] || [[ "$(cat "$SERVICE_ROOT/ID")" != "$ID" ]]; then
      [[ -z $QUIET ]] && dokku_log_warn "Updating local container ID"
      echo "$ID" >"$SERVICE_ROOT/ID"
    fi
    return 0
  fi

  dokku_log_info2_quiet "Starting container"
  local PREVIOUS_ID=$("$DOCKER_BIN" container ps -aq --no-trunc --filter "status=exited" --filter "name=^/$SERVICE_NAME$") || true

  if [[ -n $PREVIOUS_ID ]]; then
    "$DOCKER_BIN" container start "$PREVIOUS_ID" >/dev/null
    service_port_reconcile_status "$SERVICE"
    dokku_log_info2 "Container started"
  elif service_image_exists "$SERVICE"; then
    service_create_container "$SERVICE"
  else
    if ! service_image_exists "$SERVICE"; then
      [[ -f "$SERVICE_ROOT/IMAGE" ]] && PLUGIN_IMAGE="$(cat "$SERVICE_ROOT/IMAGE")"
      [[ -f "$SERVICE_ROOT/IMAGE_VERSION" ]] && PLUGIN_IMAGE_VERSION="$(cat "$SERVICE_ROOT/IMAGE_VERSION")"
      dokku_log_verbose_quiet "Missing image $PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION for $SERVICE"
    else
      dokku_log_verbose_quiet "Neither container nor valid configuration exists for $SERVICE"
    fi
  fi
}

service_url() {
  local SERVICE="$1"
  local SERVICE_DNS_HOSTNAME="$(service_dns_hostname "$SERVICE")"
  local DATABASE_NAME="$(get_database_name "$SERVICE")"
  echo "$PLUGIN_SCHEME://$SERVICE_DNS_HOSTNAME:${PLUGIN_DATASTORE_PORTS[0]}/$DATABASE_NAME"
}
