#!/usr/bin/env bash

set -eo pipefail
shopt -s nullglob

WHEREAMI="$(cd "$(dirname "$0")" && pwd)"

# ----------------- Check if User Provided Parameters are Set ------------------

. "${WHEREAMI}"/chk-usr-env

# ----------------------- Set Common Default Parameters ------------------------

. "${WHEREAMI}"/set-default-env

# --------------------------- Set Default Parameters ---------------------------

MANAGER_CONFIG_DIR=${MANAGER_CONFIG_DIR:-"/etc/opt/imply/manager"}

IMPLY_MANAGER_DEFAULTS_UPDATE_TYPE=${IMPLY_MANAGER_DEFAULTS_UPDATE_TYPE:-"disabled"}
IMPLY_MANAGER_STORE_CA_JKS_PATH=${IMPLY_MANAGER_STORE_CA_JKS_PATH:-"${TLS_DIR:?}/manager-store-ca.jks"}
IMPLY_MANAGER_STORE_CLIENT_JKS_PATH=${IMPLY_MANAGER_STORE_CLIENT_JKS_PATH:-"${TLS_DIR:?}/manager-store-client.jks"}
IMPLY_MANAGER_STORE_CLIENT_PK8_PATH=${IMPLY_MANAGER_STORE_CLIENT_PK8_PATH:-"${TLS_DIR:?}/manager-store-client-key.pk8"}
IMPLY_MANAGER_LOGLEVEL=${IMPLY_MANAGER_LOGLEVEL:-info}
IMPLY_MANAGER_SQL_LOGLEVEL=${IMPLY_MANAGER_SQL_LOGLEVEL:-info}
IMPLY_MANAGER_HTTP_LOGLEVEL=${IMPLY_MANAGER_HTTP_LOGLEVEL:-info}
IMPLY_MANAGER_USE_MANAGER_STORE_CA_AS_CLUSTER_DEFAULT=${IMPLY_MANAGER_USE_MANAGER_STORE_CA_AS_CLUSTER_DEFAULT:-true}
IMPLY_MANAGER_USE_MANAGER_STORE_CLIENT_CERT_AS_CLUSTER_DEFAULT=${IMPLY_MANAGER_USE_MANAGER_STORE_CLIENT_CERT_AS_CLUSTER_DEFAULT:-true}

# --------------------- Maybe Generate Manager TLS Assets ----------------------

. "${WHEREAMI}"/gen-mgr-tls-assets

# ------------------ Maybe Generate Manager Store TLS Assets -------------------

. "${WHEREAMI}"/gen-mgr-store-tls-assets

# ---------------------------- Generate logback.xml ----------------------------

cat <<EOT > "${MANAGER_CONFIG_DIR}/logback.xml"
<!--This file was automatically generated and should not be edited-->

<configuration>
  <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{ISO8601} [%thread] %X{emitFlag:--} %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="io.imply" level="${IMPLY_MANAGER_LOGLEVEL}" additivity="false">
    <appender-ref ref="STDOUT" />
  </logger>

  <logger name="org.skife.jdbi.v2" level="${IMPLY_MANAGER_SQL_LOGLEVEL}" additivity="false">
    <appender-ref ref="STDOUT" />
  </logger>

  <logger name="org.eclipse.jetty" level="${IMPLY_MANAGER_HTTP_LOGLEVEL}" additivity="false">
    <appender-ref ref="STDOUT" />
  </logger>

  <root level="info">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
EOT

# ----------------------------- Generate jvm.config ----------------------------

cat <<EOT > "${MANAGER_CONFIG_DIR}/jvm.config"
-server
-Duser.timezone=UTC
-Dfile.encoding=UTF-8
-Dderby.system.home=/mnt/var/derby
-Dlogback.configurationFile=logback.xml
EOT

# -------------- Generate Config Server Repo & Agent Host Config  --------------

MANAGER_REPO_HOST_CONFIG=${MANAGER_REPO_HOST_CONFIG:-"/opt/imply/onprem/conf/manager-repo-host"}

cat <<EOT > "${MANAGER_REPO_HOST_CONFIG}" 
${IMPLY_MANAGER_HOST}:${IMPLY_MANAGER_REPO_PORT}
EOT

MANAGER_REPO_AGENT_CONFIG=${MANAGER_REPO_AGENT_CONFIG:-"/opt/imply/onprem/conf/manager-agent-host"}

cat <<EOT > "${MANAGER_REPO_AGENT_CONFIG}"
${IMPLY_MANAGER_HOST}:${IMPLY_MANAGER_AGENT_PORT}
EOT

# ------------------------- Generate runtime.properties ------------------------

MANAGER_CONFIG="${MANAGER_CONFIG_DIR}/runtime.properties"

echo "${MANAGER_CONFIG}"

cat <<EOT > "${MANAGER_CONFIG}"
#
# This file was automatically generated and should not be edited. 
#

server.host=${IMPLY_MANAGER_HOST}
server.port=${IMPLY_MANAGER_BE_PORT}
manager.superPrincipal=${IMPLY_MANAGER_SUPER_PRINCIPAL}
manager.onprem.agentEtcDirectory=/etc/opt/imply/agent
manager.onprem.groveServiceUser=${IMPLY_AGENT_USER}
manager.onprem.groveServiceGroup=${IMPLY_AGENT_GROUP}
application.cache.scope=global
application.defaultsUpdateType=${IMPLY_MANAGER_DEFAULTS_UPDATE_TYPE}
EOT

# ---------------------------- Configure License Key ---------------------------

if [[ -n "${IMPLY_MANAGER_LICENSE_KEY}" ]]; then
  IMPLY_MANAGER_LICENSE_KEY_ESCAPED=$(echo "${IMPLY_MANAGER_LICENSE_KEY}" | sed -e 's/"/\\"/g')
  cat <<EOT >> "${MANAGER_CONFIG}"
manager.onprem.licenseKey="${IMPLY_MANAGER_LICENSE_KEY_ESCAPED}"
EOT
fi

# ------------------------ Configure Authentication Token ----------------------

if [ -n "${IMPLY_MANAGER_AUTH_TOKEN}" ]; then
  cat <<EOT >> "${MANAGER_CONFIG}"
application.useAuthentication=true
server.http.username=imply
server.http.password=${IMPLY_MANAGER_AUTH_TOKEN}
application.grove.username=imply
application.grove.password=${IMPLY_MANAGER_AUTH_TOKEN}
refreshableConstants.username=imply
refreshableConstants.password=${IMPLY_MANAGER_AUTH_TOKEN}
EOT
fi

# -------------------------------- Configure TLS -------------------------------

if [[ -f "${IMPLY_MANAGER_CA_KEY_PATH}" && -f "${IMPLY_MANAGER_CA_CERT_PATH}" ]]; then
  cat <<EOT >> "${MANAGER_CONFIG}"
server.http.keyStorePath=${TLS_DIR}/onprem.jks
server.http.keyStorePassword=onprem
security.keyStoreFilename=${TLS_DIR}/ca.jks
security.keyStorePassword=onprem
security.signingPrivateKeyPassword=onprem
application.useTls=true
refreshableConstants.httpRepositoryHost=https://${IMPLY_MANAGER_HOST}:${IMPLY_MANAGER_REPO_PORT}/repo
EOT
else
  cat <<EOT >> "${MANAGER_CONFIG}"
refreshableConstants.httpRepositoryHost=http://${IMPLY_MANAGER_HOST}:${IMPLY_MANAGER_REPO_PORT}/repo
EOT
fi

# ------------------------ Define TLS Connection Params ------------------------

if [[ -f "${IMPLY_MANAGER_STORE_CA_CERT_PATH}" ]]; then

  # ------------------------ Maybe Set TLS Default Params ------------------------

  if [[ "${IMPLY_MANAGER_USE_MANAGER_STORE_CA_AS_CLUSTER_DEFAULT}" == "true" && -z "${imply_defaults_metadataStorageTlsCert}" ]]; then
    echo "defaults.metadataStorageTlsCert=$(awk '{printf "%s\\n", $0}' "${IMPLY_MANAGER_STORE_CA_CERT_PATH}")" >> "${MANAGER_CONFIG}"
  fi

  # ----------------------- Define MySQL Connection Params -----------------------

  # MySQL with TLS
  if [[ "${IMPLY_MANAGER_STORE_TYPE}" == "mysql" ]]; then
    IMPLY_MANAGER_STORE_SSLMODE=${IMPLY_MANAGER_STORE_SSLMODE:-"VERIFY_CA"}

    CONNECTION_PARAMS=(
      "autoReconnect=true"
      "sslMode=${IMPLY_MANAGER_STORE_SSLMODE}"
      "useSSL=true"
      "requireSSL=true"
      "verifyServerCertificate=true"
      "trustCertificateKeyStoreUrl=file://${IMPLY_MANAGER_STORE_CA_JKS_PATH}"
      "trustCertificateKeyStorePassword=imply-onprem"
    )

  # --------------------- Define PostgreSQL Connection Params --------------------

  # PostgreSQL with TLS
  elif [[ "${IMPLY_MANAGER_STORE_TYPE}" == "postgresql" ]]; then
    IMPLY_MANAGER_STORE_SSLMODE=${IMPLY_MANAGER_STORE_SSLMODE:-"verify-ca"}

    CONNECTION_PARAMS=(
      "sslmode=${IMPLY_MANAGER_STORE_SSLMODE}"
      "sslrootcert=${IMPLY_MANAGER_STORE_CA_CERT_PATH}"
    )

  fi

  # ---------------------- Maybe set Client Cert Key Pair ------------------------

  if [[ -f "${IMPLY_MANAGER_STORE_CLIENT_CERT_PATH}" && -f "${IMPLY_MANAGER_STORE_CLIENT_KEY_PATH}" ]]; then

    # ------------------------ Maybe Set TLS Default Params ------------------------

    if [[ "${IMPLY_MANAGER_USE_MANAGER_STORE_CLIENT_CERT_AS_CLUSTER_DEFAULT}" == "true" && -z "${imply_defaults_metadataStorageClientCert}" && -z "${imply_defaults_metadataStorageClientKey}" ]]; then
      echo "defaults.metadataStorageClientCert=$(awk '{printf "%s\\n", $0}' "${IMPLY_MANAGER_STORE_CLIENT_CERT_PATH}")" >> "${MANAGER_CONFIG}"
      echo "defaults.metadataStorageClientKey=$(awk '{printf "%s\\n", $0}' "${IMPLY_MANAGER_STORE_CLIENT_KEY_PATH}")" >> "${MANAGER_CONFIG}"
    fi

    if [[ "${IMPLY_MANAGER_STORE_TYPE}" == "mysql" ]]; then  
      CONNECTION_PARAMS+=(
        "clientCertificateKeyStoreUrl=file://${IMPLY_MANAGER_STORE_CLIENT_JKS_PATH}"
        "clientCertificateKeyStorePassword=imply-onprem"
      )
    else
      CONNECTION_PARAMS+=(
        "sslcert=${IMPLY_MANAGER_STORE_CLIENT_CERT_PATH}"
        "sslkey=${IMPLY_MANAGER_STORE_CLIENT_PK8_PATH}"
      )
    fi

  fi

# MySQL without TLS
elif [[ "${IMPLY_MANAGER_STORE_TYPE}" == "mysql" ]]; then
  CONNECTION_PARAMS=("autoReconnect=true")

# PostgreSQL without TLS
else
  CONNECTION_PARAMS=() 
fi

# ----------------------- Build Manager Store Connect URI ----------------------

IMPLY_MANAGER_CONNECT_URI="${IMPLY_MANAGER_STORE_TYPE}://"
IMPLY_MANAGER_CONNECT_URI+="${IMPLY_MANAGER_STORE_HOST}:"
IMPLY_MANAGER_CONNECT_URI+="${IMPLY_MANAGER_STORE_PORT}/"
IMPLY_MANAGER_CONNECT_URI+="${IMPLY_MANAGER_STORE_DATABASE}"

if [[ -z "${IMPLY_MANAGER_STORE_CONNECTION_PARAMS}" && "${#CONNECTION_PARAMS[@]}" -gt 0 ]]; then 
  IMPLY_MANAGER_CONNECT_URI+="?$(IFS='&'; echo "${CONNECTION_PARAMS[*]}")"
else
  IMPLY_MANAGER_CONNECT_URI+="${IMPLY_MANAGER_STORE_CONNECTION_PARAMS}"
fi

unset CONNECTION_PARAMS

# ------------------- Configure Connection to Manager Store --------------------

if [[ -n "${IMPLY_MANAGER_STORE_SSLMODE}" ]]; then
  cat <<EOT >> "${MANAGER_CONFIG}"
configServer.metadataStoreSslMode=${IMPLY_MANAGER_STORE_SSLMODE}
EOT
fi

cat <<EOT >> "${MANAGER_CONFIG}"
storage.type=${IMPLY_MANAGER_STORE_TYPE}
storage.connector.connectURI=jdbc:${IMPLY_MANAGER_CONNECT_URI}
storage.connector.user=${IMPLY_MANAGER_STORE_USER}
storage.connector.password=${IMPLY_MANAGER_STORE_PASSWORD}
EOT

# ------------------------ Configure Optional Parameters -----------------------

for VAR in $(compgen -v imply_); do
  # Strip "imply_" prefix and replace underscores with periods
  PROPERTY_NAME=$(echo "${VAR}" | sed -e "s/^imply_//" -e "s/_/./g")

  # Ensure newlines are properly escaped
  PROPERTY_VALUE=${!VAR//$'\n'/\\n}

  echo "${PROPERTY_NAME}=${PROPERTY_VALUE}" >> "${MANAGER_CONFIG}"
done

# ------------------------------ Log Configuration -----------------------------

if "${VERBOSE_CONFIG_GEN}"; then
  echo -e "\n[${MANAGER_CONFIG}]"

  sed 's/^\(.*password[^=]*=\).*$/\1**********/gI' "${MANAGER_CONFIG}" |
    sed 's/^\(.*licenseKey[^=]*=\).*$/\1**********/gI' |
    sed 's/^\(.*SecretKey[^=]*=\).*$/\1**********/gI'
fi
