#!/usr/bin/env bash
set -e -o pipefail

backup-configuration() {
  declare desc="create a backup of the current configuration"
  local BACKUP_ROOT_DIRECTORY="$1"; shift
  local BACKUP_DIRECTORY="$1"; shift
  local BACKUP_SOURCES="etc/nginx etc/ImageMagick-7 etc/ssh/sshd_config etc/ssmtp etc/varnish etc/supervisord.conf usr/local/etc"

  for SOURCE in $BACKUP_SOURCES; do
    echo "Creating backup of $BACKUP_ROOT_DIRECTORY/$SOURCE to $BACKUP_DIRECTORY"
    cd "$BACKUP_ROOT_DIRECTORY/"
    cp --archive --parents "$SOURCE" "$BACKUP_DIRECTORY"
  done

  return 0
}

generate-configuration() {
  declare desc="generate the configuration based on the templates and supplied values"
  local COMMAND="${1:-custom}"

  # These environment variables are coming from https://coveooss.github.io/gotemplate/docs/cli_usage/
  export GOTEMPLATE_IMPORT=${GOTEMPLATE_IMPORT:="/easywp/configuration-overrides.yaml"}
  export GOTEMPLATE_SOURCE=${GOTEMPLATE_SOURCE:="/easywp/configuration-templates"}
  export GOTEMPLATE_TARGET=${GOTEMPLATE_TARGET:="/"}
  # This fixes the "open : no such file or directory" issue when running via KubeExecutor
  export GOTEMPLATE_NO_STDIN=1

  case "$COMMAND" in
    default)
      # Ensure we're not using the configuration-overrides.yaml to template the configuration
      export GOTEMPLATE_IMPORT=""
      # Generate the default configuration
      gotemplate \
        --no-razor \
        --ignore-missing-import \
        --recursive \
        --patterns='*.conf,*.ini,*.vcl,*.xml,sshd_config,revaliases'
    ;;
    custom)
      # Generate the customized configuration
      gotemplate \
        --no-razor \
        --ignore-missing-import \
        --recursive \
        --patterns='*.conf,*.ini,*.vcl,*.xml,sshd_config,revaliases'
    ;;
  esac

  return 0
}

validate-configuration() {
  declare desc="validate the templated configuration"
  local failed=0

  echo -n "Validating NGiNX configuration "

  NGINX_VALIDATE_OUTPUT=$(nginx -t 2>&1 | grep -v "syntax is ok\|test is successful" )
  if [[ -z $NGINX_VALIDATE_OUTPUT ]]; then
    echo "OK"
  else
    echo "FAILED"
    echo "Output:"
    echo "$NGINX_VALIDATE_OUTPUT"
    echo "Validate the NGiNX configuration using the 'nginx -t' command."
    failed=1
  fi

  echo -n "Validating PHP and PHP-FPM configuration: "
  PHP_VALIDATE_OUTPUT=$(php-fpm -t 2>&1 | grep -i "warning\|error")

  if [[ -z $PHP_VALIDATE_OUTPUT ]]; then
    echo "OK"
  else
    echo "FAILED"
    echo "Output:"
    echo "$PHP_VALIDATE_OUTPUT"
    echo "Validate the PHP and PHP-FPM configuration using the 'php-fpm -t' command."
    failed=1
  fi

  echo -n "Validating Varnish configuration "
  VARNISH_VALIDATE_OUTPUT=$(varnishd -p vcl_path=/etc/varnish/vcl.d -C -f /etc/varnish/default.vcl 2>&1 | grep "VCL compilation failed")

  if [[ -z $VARNISH_VALIDATE_OUTPUT ]]; then
    echo "OK"
  else
    echo "FAILED"
    echo "Output:"
    echo "$VARNISH_VALIDATE_OUTPUT"
    echo "Validate the Varnish configuration using the 'varnishd -p vcl_path=/etc/varnish/vcl.d -C -f /etc/varnish/default.vcl' command."
    failed=1
  fi

  return "$failed"
}

restore-configuration() {
  declare desc="restore configuration from backup"
  local BACKUP_DIRECTORY="$1"; shift
  local RESTORE_DIRECTORY=${RESTORE_DIRECTORY:=""}

  echo "Restoring configuration from backup ($BACKUP_DIRECTORY)"
  cp -a $BACKUP_DIRECTORY/* $RESTORE_DIRECTORY/ && return 0 || return 1
}

main() {
  declare desc="main function"
  local COMMAND="$1"
  local DATE="$(date +"%Y-%m-%d-%H-%M-%S")"
  local BACKUP_ROOT_DIRECTORY=${BACKUP_ROOT_DIRECTORY:=""}
  local BACKUP_DIRECTORY=${BACKUP_DIRECTORY:="$(mktemp -d /var/tmp/$DATE.XXXXXX)"}
  local EXITCODE=0

  case "$COMMAND" in
    startup)
      generate-configuration
      if ! validate-configuration; then
        echo "Configuration validation failed "
        # Generate the default configuration when validation fails during startup
        generate-configuration default
      fi
    ;;
    *)
      backup-configuration  "$BACKUP_ROOT_DIRECTORY" "$BACKUP_DIRECTORY"
      generate-configuration
      if ! validate-configuration; then
        EXITCODE=1
        echo "Configuration validation failed "
        # Restore the previous configuration when validation failed
        restore-configuration "$BACKUP_DIRECTORY"
      fi
      supervisorctl restart all
    ;;
  esac

  exit "$EXITCODE"
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  main "$@"
fi
