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

config_create () {
  [ -f $ENV_FILE ] || {
    touch $ENV_FILE
  }
}

config_styled_hash () {
  vars="$1"
  prefix="$2"

  longest=""
  while read -r word; do
    KEY=$(echo $word | cut -d"=" -f1)
    if [ ${#KEY} -gt ${#longest} ]; then
      longest=$KEY
    fi
  done <<< "$vars"

  while read -r word; do
    KEY=$(echo $word | cut -d"=" -f1)
    VALUE=$(echo $word | cut -d"=" -f2- | sed -e "s/^'//" -e "s/'$//" -e "s/\$$//g")

    num_zeros=$((${#longest} - ${#KEY}))
    zeros=" "
    while [ $num_zeros -gt 0 ]; do
      zeros="$zeros "
      num_zeros=$((num_zeros - 1))
    done
    echo "$prefix$KEY:$zeros$VALUE"
  done <<< "$vars"
}

config_write() {
  ENV_TEMP="$1"
  ENV_FILE_TEMP="${ENV_FILE}.tmp"

  echo "$ENV_TEMP" | sed '/^$/d' | sort > $ENV_FILE_TEMP
  if ! cmp -s $ENV_FILE $ENV_FILE_TEMP; then
    cp -f $ENV_FILE_TEMP $ENV_FILE
    chmod 600 $ENV_FILE
  fi
  rm -f $ENV_FILE_TEMP
}

parse_config_args() {
  case "$2" in
    --global)
      ENV_FILE="$DOKKU_ROOT/ENV"
      DOKKU_CONFIG_TYPE="global"
      DOKKU_CONFIG_RESTART=false
      ;;
    --no-restart)
      APP="$3"
      ENV_FILE="$DOKKU_ROOT/$APP/ENV"
      DOKKU_CONFIG_RESTART=false
      DOKKU_CONFIG_TYPE="app"
      set -- "${@:1:1}" "${@:3}"
  esac

  APP=${APP:="$2"}
  ENV_FILE=${ENV_FILE:="$DOKKU_ROOT/$APP/ENV"}
  DOKKU_CONFIG_TYPE=${DOKKU_CONFIG_TYPE:="app"}
  DOKKU_CONFIG_RESTART=${DOKKU_CONFIG_RESTART:=true}

  if [[ "$DOKKU_CONFIG_TYPE" = "app" ]]; then
    if [[ -z $APP ]]; then
      echo "Please specify an app to run the command on" >&2 && exit 1
    else
      verify_app_name "$2"
    fi
  fi
  export APP ENV_FILE DOKKU_CONFIG_TYPE DOKKU_CONFIG_RESTART
}

case "$1" in
  config)
    parse_config_args "$@"
    config_create

    [[ "$APP" ]] && DOKKU_CONFIG_TYPE=$APP
    [[ ! -s $ENV_FILE ]] && echo "no config vars for $DOKKU_CONFIG_TYPE" && exit 1

    VARS=$(grep -Eo "export ([a-zA-Z_][a-zA-Z0-9_]*=.*)" $ENV_FILE | cut -d" " -f2-)

    for var in "$@"; do
      if [[ "$var" == "--shell" ]]; then
        echo $VARS
        exit 0
      fi
    done


    dokku_log_info2_quiet "$DOKKU_CONFIG_TYPE config vars"
    config_styled_hash "$VARS"
    ;;

  config:get)
    parse_config_args "$@"

    if [[ -z $3 ]]; then
      echo "Usage: dokku config:get APP KEY"
      echo "Must specify KEY."
      exit 1
    fi

    config_create
    if [[ ! -s $ENV_FILE ]] ; then
      exit 0
    fi

    KEY="$3"

    grep -Eo "export ([a-zA-Z_][a-zA-Z0-9_]*=.*)" $ENV_FILE | grep "^export $KEY=" | cut -d"=" -f2- | sed -e "s/^'//" -e "s/'$//"
    ;;

  config:set)
    parse_config_args "$@"
    [[ "$2" = "--no-restart" ]] && set -- "${@:1:1}" "${@:3}"

    if [[ -z "${*:3}" ]]; then
      echo "Usage: dokku config:set APP KEY1=VALUE1 [KEY2=VALUE2 ...]"
      echo "Must specify KEY and VALUE to set."
      exit 1
    fi

    config_create
    ENV_ADD=""
    ENV_TEMP=$(cat "${ENV_FILE}")
    RESTART_APP=false
    shift 2

    for var; do
      if [[ $var != *"="* ]]; then
        echo "Usage: dokku config:set APP KEY1=VALUE1 [KEY2=VALUE2 ...]"
        echo "Must specify KEY and VALUE to set."
        exit 1
      fi
    done

    for var; do
      KEY=$(echo ${var} | cut -d"=" -f1)
      VALUE=$(echo ${var} | cut -d"=" -f2-)

      if [[ $KEY =~ [a-zA-Z_][a-zA-Z0-9_]* ]]; then
        RESTART_APP=true
        ENV_TEMP=$(echo "${ENV_TEMP}" | sed "/^export $KEY=/ d")
        ENV_TEMP="${ENV_TEMP}
export $KEY='$VALUE'"
        ENV_ADD=$(echo -e "${ENV_ADD}" | sed "/^$KEY=/ d")
        ENV_ADD="${ENV_ADD}$
${var}"
      fi
    done
    ENV_ADD=$(echo "$ENV_ADD" | tail -n +2) #remove first empty line

    if [ $RESTART_APP ]; then
      dokku_log_info1 "Setting config vars"
      config_styled_hash "$ENV_ADD" "       "

      config_write "$ENV_TEMP"
    fi

    if [[ "$DOKKU_CONFIG_RESTART" == "true" ]]; then
      dokku_log_info1 "Restarting app $APP"
      dokku ps:restart $APP
    fi
    ;;

  config:unset)
    parse_config_args "$@"
    [[ "$2" = "--no-restart" ]] && set -- "${@:1:1}" "${@:3}"

    if [[ -z $3 ]]; then
      echo "Usage: dokku config:unset APP KEY1 [KEY2 ...]"
      echo "Must specify KEY to unset."
      exit 1
    fi

    config_create
    ENV_TEMP=$(cat "${ENV_FILE}")
    VARS="${*:3}"

    for var in $VARS; do
      dokku_log_info1 "Unsetting $var"
      ENV_TEMP=$(echo -e "${ENV_TEMP}" | sed "/^export $var=/ d")

      config_write "$ENV_TEMP"
    done

    if [[ "$DOKKU_CONFIG_RESTART" == "true" ]]; then
      dokku_log_info1 "Restarting app $APP"
      dokku ps:restart $APP
    fi
    ;;

  config:set-norestart)
    dokku_log_info2 "$1 is deprecated as of v0.3.22"
    shift 1
    dokku config:set --no-restart "$@"
    ;;

  config:unset-norestart)
    dokku_log_info2 "$1 is deprecated as of v0.3.22"
    shift 1
    dokku config:unset --no-restart "$@"
    ;;

  help | config:help)
    cat && cat<<EOF
    config (<app>|--global), Display all global or app-specific config vars
    config:get (<app>|--global) KEY, Display a global or app-specific config value
    config:set (<app>|--global) KEY1=VALUE1 [KEY2=VALUE2 ...], Set one or more config vars
    config:unset (<app>|--global) KEY1 [KEY2 ...], Unset one or more config vars
EOF
    ;;

  *)
    exit $DOKKU_NOT_IMPLEMENTED_EXIT
    ;;

esac
