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

restart_nginx () {
  case "$DOKKU_DISTRO" in
    ubuntu)
      sudo /etc/init.d/nginx reload > /dev/null
      ;;

    opensuse)
      sudo /sbin/service nginx reload > /dev/null
      ;;
  esac
}

case "$1" in
  nginx:build-config)
    APP="$2"; DOKKU_APP_LISTEN_PORT="$3"; DOKKU_APP_LISTEN_IP="${4}"
    VHOST_PATH="$DOKKU_ROOT/$APP/VHOST"
    URLS_PATH="$DOKKU_ROOT/$APP/URLS"
    WILDCARD_SSL="$DOKKU_ROOT/tls"
    SSL="$DOKKU_ROOT/$APP/tls"

    if [[ -z "$DOKKU_APP_LISTEN_PORT" ]] && [[ -f "$DOKKU_ROOT/$APP/PORT" ]]; then
      DOKKU_APP_LISTEN_PORT=$(< "$DOKKU_ROOT/$APP/PORT")
    fi
    if [[ -z "$DOKKU_APP_LISTEN_IP" ]] && [[ -f "$DOKKU_ROOT/$APP/IP" ]]; then
      DOKKU_APP_LISTEN_IP=$(< "$DOKKU_ROOT/$APP/IP")
    fi

    [[ -f "$DOKKU_ROOT/ENV" ]] && source $DOKKU_ROOT/ENV
    [[ -f "$DOKKU_ROOT/$APP/ENV" ]] && source $DOKKU_ROOT/$APP/ENV

    if [[ ! -n "$NO_VHOST" ]] && [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
      NONSSL_VHOSTS=$(cat $VHOST_PATH)
      if [[ -e "$SSL/server.crt" ]] && [[ -e "$SSL/server.key" ]]; then
        SSL_INUSE="$SSL"
        SSL_DIRECTIVES=$(cat <<EOF
  ssl_certificate     $SSL_INUSE/server.crt;
  ssl_certificate_key $SSL_INUSE/server.key;
EOF
)
      elif  [[ -e "$WILDCARD_SSL/server.crt" ]] && [[ -e "$WILDCARD_SSL/server.key" ]]; then
        SSL_INUSE="$WILDCARD_SSL"
        SSL_DIRECTIVES=""
      fi

      NGINX_CONF=$(mktemp -t "nginx.conf.XXXXXX")
      SCHEME="http"
      if [[ -n "$SSL_INUSE" ]]; then
        SCHEME="https"

        SSL_HOSTNAME=$(openssl x509 -in $SSL_INUSE/server.crt -noout -subject | tr '/' '\n' | grep CN= | cut -c4-)
        if [[ -n "$SSL_HOSTNAME" ]]; then
          SSL_HOSTNAME_REGEX=$(echo "$SSL_HOSTNAME" | sed 's|\.|\\.|g' | sed 's/\*/\[^\.\]\*/g')
          [[ -z "$(egrep "^${SSL_HOSTNAME_REGEX}$" $VHOST_PATH)" ]] && echo "$SSL_HOSTNAME" >> $VHOST_PATH
        fi

        SSL_HOSTNAME_ALT=$(openssl x509 -in $SSL_INUSE/server.crt -noout -text | grep --after-context=1 '509v3 Subject Alternative Name:' | tail -n 1 | sed -e "s/[[:space:]]*DNS://g"  | tr ',' '\n' || true)
        if [[ -n "$SSL_HOSTNAME_ALT" ]]; then
          SSL_HOSTNAME_ALT_REGEX=$(echo "$SSL_HOSTNAME_ALT" | sed 's|\.|\\.|g' | sed 's/\*/\[^\.\]\*/g')
          [[ -z "$(egrep "^${SSL_HOSTNAME_ALT_REGEX}$" $VHOST_PATH)" ]] && echo "$SSL_HOSTNAME_ALT" >> $VHOST_PATH
        fi

        SSL_VHOSTS=$(egrep "^${SSL_HOSTNAME_REGEX}$|^${SSL_HOSTNAME_ALT_REGEX}$" $VHOST_PATH || exit 0)
        NONSSL_VHOSTS=$(egrep -v "^${SSL_HOSTNAME}$|^${SSL_HOSTNAME_ALT}$" $VHOST_PATH || exit 0)

        NGINX_TEMPLATE="$PLUGIN_PATH/nginx-vhosts/templates/nginx.ssl.conf.template"
        while read line; do
          dokku_log_info1 "Configuring SSL for $line..."
          SSL_SERVER_NAME=$line
          NOSSL_SERVER_NAME=$line
          eval "cat <<< \"$(< $NGINX_TEMPLATE)\" >> $NGINX_CONF"
        done <<< "$SSL_VHOSTS"
      fi

      NOSSL_SERVER_NAME=$(echo $NONSSL_VHOSTS | tr '\n' ' ')
      APP_NGINX_TEMPLATE="$DOKKU_ROOT/$APP/nginx.conf.template"
      if [[ -f $APP_NGINX_TEMPLATE ]]; then
        dokku_log_info1 "Overriding default nginx.conf with detected nginx.conf.template"
        eval "cat <<< \"$(< $APP_NGINX_TEMPLATE)\" > $NGINX_CONF"
      elif [[ -n "$NONSSL_VHOSTS" ]]; then
        xargs -i echo "-----> Configuring {}..." <<< "$NONSSL_VHOSTS"
        NGINX_TEMPLATE="$PLUGIN_PATH/nginx-vhosts/templates/nginx.conf.template"
        eval "cat <<< \"$(< $NGINX_TEMPLATE)\" >> $NGINX_CONF"
      fi

      if [[ -n "$DOKKU_APP_LISTEN_PORT" ]] && [[ -n "$DOKKU_APP_LISTEN_IP" ]]; then
        echo "upstream $APP { server $DOKKU_APP_LISTEN_IP:$DOKKU_APP_LISTEN_PORT; }" >> $NGINX_CONF
      fi

      dokku_log_info1 "Creating $SCHEME nginx.conf"
      mv $NGINX_CONF "$DOKKU_ROOT/$APP/nginx.conf"

      if [[ -n "$DOKKU_APP_LISTEN_PORT" ]] && [[ -n "$DOKKU_APP_LISTEN_IP" ]]; then
        dokku_log_info1 "Running nginx-pre-reload"
        pluginhook nginx-pre-reload $APP $DOKKU_APP_LISTEN_PORT $DOKKU_APP_LISTEN_IP

        echo "       Reloading nginx"
        restart_nginx
      fi

      echo "# THIS FILE IS GENERATED BY DOKKU - DO NOT EDIT, YOUR CHANGES WILL BE OVERWRITTEN" > $URLS_PATH
      xargs -i echo "https://{}" <<< "${SSL_VHOSTS}" >> $URLS_PATH
      xargs -i echo "http://{}" <<< "${NONSSL_VHOSTS}" >> $URLS_PATH
    else
      if [[ -f "$DOKKU_ROOT/$APP/VHOST" ]]; then
        dokku_log_info1 "VHOST support disabled, deleting $APP/VHOST"
        rm "$DOKKU_ROOT/$APP/VHOST"
      fi
      if [[ -f "$DOKKU_ROOT/$APP/nginx.conf" ]]; then
        dokku_log_info1 "VHOST support disabled, deleting nginx.conf"
        rm "$DOKKU_ROOT/$APP/nginx.conf"

        dokku_log_info1 "VHOST support disabled, reloading nginx after nginx.conf deletion"
        restart_nginx
      fi
    fi
    ;;

  nginx:import-ssl)
    [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
    verify_app_name "$2"
    [[ -t 0 ]] && echo "Tar archive containing server.crt and server.key expected on stdin" && exit 1
    APP="$2"

    TEMP_DIR=$(mktemp -d)
    cd $TEMP_DIR
    tar xvf - <&0
    [[ ! -f "$TEMP_DIR/server.crt" ]] && echo "Tar archive missing server.crt" && exit 1
    [[ ! -f "$TEMP_DIR/server.key" ]] && echo "Tar archive missing server.key" && exit 1

    mkdir -p "$DOKKU_ROOT/$APP/tls"
    mv "$TEMP_DIR/server.crt" "$DOKKU_ROOT/$APP/tls/server.crt"
    mv "$TEMP_DIR/server.key" "$DOKKU_ROOT/$APP/tls/server.key"
    cd $DOKKU_ROOT
    rm -rf $TEMP_DIR
    dokku nginx:build-config $APP
    ;;

  help | nginx:help)
    cat && cat<<EOF
    nginx:import-ssl <app>                          Imports a tarball from stdin; should contain server.crt and server.key
    nginx:build-config <app>                        (Re)builds nginx config for given app
EOF
    ;;

  *)
    exit $DOKKU_NOT_IMPLEMENTED_EXIT
    ;;

esac
