#!/usr/bin/env bash
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/traefik-vhosts/internal-functions"
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x

trigger-traefik-vhosts-docker-args-process-deploy() {
  declare desc="nginx-vhosts core-post-deploy plugin trigger"
  declare trigger="docker-args-process-deploy"
  declare APP="$1" IMAGE_SOURCE_TYPE="$2" IMAGE_TAG="$3" PROC_TYPE="$4" CONTAINER_INDEX="$5"
  local app_domains is_app_listening letsencrypt_email output proxy_container_port proxy_host_port port_map proxy_scheme proxy_schemes traefik_domains
  local proxy_container_http_port proxy_container_http_port_candidate proxy_host_http_port_candidate
  local proxy_container_https_port proxy_container_https_port_candidate proxy_host_https_port_candidate
  local STDIN=$(cat)

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

  if [[ "$(plugn trigger proxy-type "$APP")" != "traefik" ]]; then
    return
  fi

  if [[ "$(plugn trigger proxy-is-enabled "$APP")" != "true" ]]; then
    return
  fi

  if ! plugn trigger domains-vhost-enabled "$APP" 2>/dev/null; then
    return
  fi

  # ensure we have a port mapping
  plugn trigger ports-configure "$APP"

  # gather port mapping information
  # we only support proxying a single port for http and https listeners
  # so this block parses the port mappings and tries to find the correct
  # mapping to expose
  is_app_listening="false"
  while read -r port_map; do
    proxy_scheme="$(awk -F ':' '{ print $1 }' <<<"$port_map")"
    proxy_host_port="$(awk -F ':' '{ print $2 }' <<<"$port_map")"
    proxy_container_port="$(awk -F ':' '{ print $3 }' <<<"$port_map")"

    if [[ "$proxy_scheme" == "http" ]]; then
      is_app_listening="true"
      if [[ -z "$proxy_container_http_port_candidate" ]]; then
        proxy_container_http_port_candidate="$proxy_container_port"
        proxy_host_http_port_candidate="$proxy_host_port"
      fi

      if [[ "$proxy_host_port" == "80" ]] && [[ -z "$proxy_container_http_port" ]]; then
        proxy_container_http_port="$proxy_container_port"
      fi
    fi

    if [[ "$proxy_scheme" == "https" ]]; then
      is_app_listening="true"
      if [[ -z "$proxy_container_https_port_candidate" ]]; then
        proxy_container_https_port_candidate="$proxy_container_port"
        proxy_host_https_port_candidate="$proxy_host_port"
      fi

      if [[ "$proxy_host_port" == "443" ]] && [[ -z "$proxy_container_https_port" ]]; then
        proxy_container_https_port="$proxy_container_port"
      fi
    fi
  done < <(plugn trigger ports-get "$APP")

  letsencrypt_email="$(fn-traefik-letsencrypt-email)"
  if [[ -n "$letsencrypt_email" ]] && [[ -z "$proxy_container_https_port" ]]; then
    proxy_container_https_port_candidate="$proxy_container_http_port_candidate"
    proxy_host_https_port_candidate="$proxy_host_http_port_candidate"
    if [[ -n "$proxy_container_http_port" ]]; then
      proxy_container_https_port_candidate="$proxy_container_http_port"
      proxy_host_http_port_candidate=443
    fi
  fi

  # add the labels for traefik here
  # any `http:80` port mapping is treated as a `http` traefik entrypoint
  # any `https:443` port mapping is treated as a `https` traefik entrypoint
  if [[ -n "$is_app_listening" ]]; then
    app_domains="$(plugn trigger domains-list "$APP")"
    if [[ -n "$app_domains" ]]; then
      # get length of domains
      if [[ "$(echo "$traefik_domains" | wc -w)" -eq 1 ]]; then
        traefik_domains="Host(\\\`$traefik_domains\\\`)"
      else
        for domain in $(echo "$app_domains" | xargs); do
          if [[ -z "$traefik_domains" ]]; then
            traefik_domains="Host(\\\`$domain\\\`)"
            continue
          fi
          traefik_domains="$traefik_domains || Host(\\\`$domain\\\`)"
        done
      fi
    fi

    output="--label traefik.enable=true"
    if [[ -n "$proxy_container_http_port" ]] || [[ -n "$proxy_container_http_port_candidate" ]]; then
      if [[ -z "$proxy_container_http_port" ]]; then
        dokku_log_warn "Warning: http:80 port mapping not found"
        dokku_log_warn "Utilizing first http port mapping, http:$proxy_host_http_port_candidate:$proxy_container_http_port_candidate"
        proxy_container_http_port="$proxy_container_http_port_candidate"
      fi

      output="$output --label traefik.http.services.$APP-$PROC_TYPE-http.loadbalancer.server.port=$proxy_container_http_port"
      output="$output --label traefik.http.routers.$APP-$PROC_TYPE-http.entrypoints=$(fn-traefik-http-entry-point)"
      output="$output --label traefik.http.routers.$APP-$PROC_TYPE-http.service=$APP-$PROC_TYPE-http"
      if [[ -n "$traefik_domains" ]]; then
        output="$output --label \"traefik.http.routers.$APP-$PROC_TYPE-http.rule=$traefik_domains\""
      fi
    fi

    if [[ -n "$proxy_container_https_port" ]] || [[ -n "$proxy_container_https_port_candidate" ]]; then
      if [[ -z "$proxy_container_https_port" ]]; then
        dokku_log_warn "Warning: https:443 port mapping not found"
        dokku_log_warn "Utilizing first https port mapping, http:$proxy_host_https_port_candidate:$proxy_container_https_port_candidate"
        proxy_container_https_port="$proxy_container_https_port_candidate"
      fi

      output="$output --label traefik.http.services.$APP-$PROC_TYPE-https.loadbalancer.server.port=$proxy_container_https_port"
      output="$output --label traefik.http.routers.$APP-$PROC_TYPE-https.entrypoints=$(fn-traefik-https-entry-point)"
      output="$output --label traefik.http.routers.$APP-$PROC_TYPE-https.service=$APP-$PROC_TYPE-https"
      output="$output --label traefik.http.routers.$APP-$PROC_TYPE-https.tls.certresolver=leresolver"
      if [[ -n "$traefik_domains" ]]; then
        output="$output --label \"traefik.http.routers.$APP-$PROC_TYPE-https.rule=$traefik_domains\""
      fi
    fi
  fi

  echo -n "$STDIN$output"
}

trigger-traefik-vhosts-docker-args-process-deploy "$@"
