#!/usr/bin/env bash
set -euo pipefail

usage() {
  printf '%s\n' \
    "Usage: $0 <local|rest|ssh|database> <environment-file> <command> [argument ...]" \
    >&2
}

if (($# < 3)); then
  usage
  exit 64
fi

mode=$1
environment_file=$2
shift 2

case "$mode" in
  local|rest|ssh|database)
    ;;
  *)
    usage
    exit 64
    ;;
esac

if [[ ! -r "$environment_file" ]]; then
  printf '%s must identify a readable environment file.\n' "$environment_file" >&2
  exit 66
fi

known_variables=(
  SITE_URL
  LOCAL_SITE_URL
  WP_LOCAL_DB_NAME
  WP_LOCAL_DB_USER
  WP_LOCAL_DB_PASSWORD
  WP_LOCAL_DB_ROOT_PASSWORD
  WP_REST_USER
  WP_REST_APPLICATION_PASSWORD
  WP_SSH_HOST
  WP_SSH_PORT
  WP_SSH_USER
  WP_SSH_KEY_PATH
  WP_SSH_KNOWN_HOSTS_PATH
  WP_REMOTE_PATH
  WP_DB_HOST
  WP_DB_PORT
  WP_DB_NAME
  WP_DB_USER
  WP_DB_PASSWORD
  WP_DB_SSL_MODE
  WP_DB_SSL_CA
)

local_variables=(
  LOCAL_SITE_URL
  WP_LOCAL_DB_NAME
  WP_LOCAL_DB_USER
  WP_LOCAL_DB_PASSWORD
  WP_LOCAL_DB_ROOT_PASSWORD
)

rest_variables=(
  SITE_URL
  WP_REST_USER
  WP_REST_APPLICATION_PASSWORD
)

ssh_variables=(
  WP_SSH_HOST
  WP_SSH_PORT
  WP_SSH_USER
  WP_SSH_KEY_PATH
  WP_SSH_KNOWN_HOSTS_PATH
  WP_REMOTE_PATH
)

database_variables=(
  WP_DB_HOST
  WP_DB_PORT
  WP_DB_NAME
  WP_DB_USER
  WP_DB_PASSWORD
  WP_DB_SSL_MODE
  WP_DB_SSL_CA
)

case "$mode" in
  local)
    selected_variables=("${local_variables[@]}")
    ;;
  rest)
    selected_variables=("${rest_variables[@]}")
    ;;
  ssh)
    selected_variables=("${ssh_variables[@]}")
    ;;
  database)
    selected_variables=("${database_variables[@]}")
    ;;
esac

declare -A known_variable_names=()
declare -A loaded_variable_names=()
declare -A loaded_variable_values=()
for variable_name in "${known_variables[@]}"; do
  known_variable_names["$variable_name"]=1
done

unset "${known_variables[@]}"

line_number=0
while IFS= read -r line || [[ -n "$line" ]]; do
  line_number=$((line_number + 1))

  if [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]]; then
    continue
  fi

  if [[ ! "$line" =~ ^([A-Z][A-Z0-9_]*)=(.*)$ ]]; then
    printf 'Line %s is not a NAME=VALUE entry.\n' "$line_number" >&2
    exit 65
  fi

  variable_name=${BASH_REMATCH[1]}
  variable_value=${BASH_REMATCH[2]}

  if [[ -z "${known_variable_names[$variable_name]:-}" ]]; then
    printf '%s is not in the environment contract.\n' "$variable_name" >&2
    exit 65
  fi

  if [[ -n "${loaded_variable_names[$variable_name]:-}" ]]; then
    printf '%s occurs more than once in the environment file.\n' \
      "$variable_name" >&2
    exit 65
  fi

  loaded_variable_names["$variable_name"]=1
  loaded_variable_values["$variable_name"]=$variable_value
done <"$environment_file"

for variable_name in "${selected_variables[@]}"; do
  if [[ -n "${loaded_variable_names[$variable_name]:-}" ]]; then
    printf -v "$variable_name" '%s' "${loaded_variable_values[$variable_name]}"
    export "$variable_name"
  fi
done

script_directory=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
"${script_directory}/validate-environment.sh" "$mode" >/dev/null

exec "$@"
