#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/config/functions"
source "$PLUGIN_AVAILABLE_PATH/proxy/functions"

network-build-config() {
  declare desc="builds network config files"
  declare APP="$1"; verify_app_name "$APP"
  local CONTAINER_INDEX DOKKU_SCALE IMAGE IS_HEROKUISH_CONTAINER PROC_COUNT PROC_LINE PROC_TYPE

  DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE"
  IS_HEROKUISH_CONTAINER=false
  IMAGE=$(get_app_image_name "$APP")
  is_image_herokuish_based "$IMAGE" && IS_HEROKUISH_CONTAINER=true

  dokku_log_info1 "Ensuring network configuration is in sync for ${APP}"
  while read -r PROC_LINE || [[ -n "$PROC_LINE" ]]; do
    [[ "$PROC_LINE" =~ ^#.* ]] && continue
    PROC_LINE="$(strip_inline_comments "$PROC_LINE")"
    PROC_TYPE=${PROC_LINE%%=*}
    PROC_COUNT=${PROC_LINE#*=}
    CONTAINER_INDEX=1
    while [[ $CONTAINER_INDEX -le $PROC_COUNT ]]; do
      local CONTAINER_ID="" p="" port="" ipaddr="" CONTAINER_STATUS
      local DOKKU_CONTAINER_ID_FILE="$DOKKU_ROOT/$APP/CONTAINER.$PROC_TYPE.$CONTAINER_INDEX"
      local DOKKU_IP_FILE="$DOKKU_ROOT/$APP/IP.$PROC_TYPE.$CONTAINER_INDEX"
      local DOKKU_PORT_FILE="$DOKKU_ROOT/$APP/PORT.$PROC_TYPE.$CONTAINER_INDEX"
      local CONTAINER_INDEX=$(( CONTAINER_INDEX + 1 ))

      [[ -f "$DOKKU_CONTAINER_ID_FILE" ]] || continue

      CONTAINER_ID="$(cat "$DOKKU_CONTAINER_ID_FILE")"
      [[ -n "$CONTAINER_ID" ]] || continue
      CONTAINER_RUNNING="$(docker inspect -f '{{.State.Running}}' "$CONTAINER_ID" 2>/dev/null || true)"
      [[ "$CONTAINER_RUNNING" == "true" ]] || continue

      ipaddr=$(network-get-container-ipaddr "$APP" "PROC_TYPE" "$IS_HEROKUISH_CONTAINER" "$CONTAINER_ID")
      port=$(network-get-container-port "$APP" "PROC_TYPE" "$IS_HEROKUISH_CONTAINER" "$CONTAINER_ID")

      [[ -n "$ipaddr" ]] && echo "$ipaddr" > "$DOKKU_IP_FILE"
      [[ -n "$port" ]] && echo "$port" > "$DOKKU_PORT_FILE"
    done
  done < "$DOKKU_SCALE_FILE"
}

network-compute-container-ports() {
  declare desc="Computes the ports for a given app container"
  declare APP="$1" PROC_TYPE="$2" IS_HEROKUISH_CONTAINER="$3"
  local DOKKU_DOCKERFILE_PORTS PORTS

  if [[ "$PROC_TYPE" != "web" ]]; then
    return
  fi

  if [[ -z "$IS_HEROKUISH_CONTAINER" ]]; then
    DOKKU_DOCKERFILE_PORTS=($(config_get "$APP" DOKKU_DOCKERFILE_PORTS || true))
  fi

  if [[ -z "${DOKKU_DOCKERFILE_PORTS[*]}" ]]; then
    local PORTS=5000
  else
    local p
    for p in ${DOKKU_DOCKERFILE_PORTS[*]};do
      if [[ ! "$p" =~ .*udp.* ]]; then
        # set port to first non-udp port
        local p=${p//\/tcp}
        local PORT=${PORT:="$p"}
      fi
      PORTS+=" $PORT "
    done
  fi

  echo "$PORTS"
}

network-get-container-ipaddr() {
  declare desc="Return the ipaddr for a given app container"
  declare APP="$1" PROC_TYPE="$2" IS_HEROKUISH_CONTAINER="$3" CONTAINER_ID="$4"
  local DOKKU_IS_APP_PROXY_ENABLED
  local IP_ADDRESS=127.0.0.1

  if [[ "$PROC_TYPE" != "web" ]]; then
    return
  fi

  local DOKKU_IS_APP_PROXY_ENABLED="$(is_app_proxy_enabled "$APP")"
  if [[ "$DOKKU_IS_APP_PROXY_ENABLED" == "true" ]]; then
    IP_ADDRESS="$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$CONTAINER_ID")"
    # Docker < 1.9 compatibility
    if [[ -z "$IP_ADDRESS" ]]; then
      IP_ADDRESS=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$CONTAINER_ID")
    fi
  fi

  echo "$IP_ADDRESS"
}

network-get-container-listeners() {
  declare desc="Return the listeners (host:port combinations) for a given app container"
  declare APP="$1" 

  local IP_FILE LISTENER_IP LISTENER_PORT LISTENERS PORT_FILE
  for IP_FILE in $DOKKU_ROOT/$APP/IP.web.*; do
    local PORT_FILE="${IP_FILE//IP/PORT}"
    local LISTENER_IP=$(< "$IP_FILE")
    local LISTENER_PORT=$(< "$PORT_FILE")
    local LISTENERS+="$LISTENER_IP:$LISTENER_PORT "
  done

  echo "$LISTENERS"
}

network-get-container-port() {
  declare desc="Return the port for a given app container"
  declare APP="$1" PROC_TYPE="$2" IS_HEROKUISH_CONTAINER="$3" CONTAINER_ID="$4"
  local DOKKU_IS_APP_PROXY_ENABLED
  local PORT=5000

  if [[ "$PROC_TYPE" != "web" ]]; then
    return
  fi

  if [[ -z "$IS_HEROKUISH_CONTAINER" ]]; then
    local DOKKU_DOCKERFILE_PORTS=($(config_get "$APP" DOKKU_DOCKERFILE_PORTS || true))
  fi

  if [[ -n "${DOKKU_DOCKERFILE_PORTS[*]}" ]]; then
    for p in ${DOKKU_DOCKERFILE_PORTS[*]};do
      if [[ ! "$p" =~ .*udp.* ]]; then
        # set port to first non-udp port
        p=${p//\/tcp}
        PORT=${port:="$p"}
      fi
    done
  fi

  DOKKU_IS_APP_PROXY_ENABLED="$(is_app_proxy_enabled "$APP")"
  if [[ "$DOKKU_IS_APP_PROXY_ENABLED" != "true" ]]; then
    PORT="$(docker port "$CONTAINER_ID" "$PORT" | sed 's/[0-9.]*://')"
  fi

  echo "$PORT"
}
