#!/bin/bash

# Copyright (c) Veeam Software Group GmbH

set -eE -u -o pipefail

SCRIPT_DIR=$(dirname "$(realpath "${BASH_SOURCE[0]}")"); readonly SCRIPT_DIR;
source "$SCRIPT_DIR/lib/error-handle.bash"
source "$SCRIPT_DIR/lib/common.bash"
source "$SCRIPT_DIR/lib/optparser.bash"
source "$SCRIPT_DIR/lib/str.bash"
source "$SCRIPT_DIR/lib/verbose.bash"

setlocale en_US.utf8 || :
# shellcheck disable=SC2034
declare -A op=()
declare -A ARGS=()

optparser-init op \
    --desc "Show or modify PostgreSQL settings."
optparser-addopt op --name "command" --narg 1 \
    --add-choice "show" \
    --add-choice "set" \
    --help "command to interact with configuration settings."
optparser-addopt op --name "name" --narg '?' \
    --help "name of the configuration parameter to show or set:" \
    --help "  $0 show listen_addresses" \
    --help "  $0 set listen_addresses='*'" \
    --help "  $0 set listen_addresses # reset to default"
optparser-addopt op -s "-v" -l "--verbose" \
    --help "provide more detailed output"
optparser-addopt op -s "-h" -l "--help" \
    --help "show this help message and exit"
optparser-ignore-required op help
optparser-parse op ARGS "$@" || exit 1
[[ -n ${ARGS[help]:-} ]] && { optparser-help op; exit 0; }
[[ -n ${ARGS[verbose]:-} ]] && { verbose-enable; }
[[ ${ARGS[command]} = set && -z ${ARGS[name]:-} ]] \
    && { printf >&2 "%s: option required: name\n" "$0"; exit 1; }

[[ $EUID -eq 0 ]] || die "script should be run as root"

trap-init

eval "$("$SCRIPT_DIR/pgsql-pkginfo")"
[[ -n ${VCTL_PGSQL_PSQL:-} ]] || die "failed to find psql binary"

psql() {
    runuser -u postgres -- "$VCTL_PGSQL_PSQL" -A -x -q -v ON_ERROR_STOP=1 "$@"
}

case "${ARGS[command]}" in
    show)
        if [[ -n ${ARGS[name]:-} && ${ARGS[name]} != all ]]; then
            psql -v "name=${ARGS[name]}" <<< "SELECT current_setting(:'name');" \
                | sed -ne "s/^current_setting|//p"
        else
            psql -c "SHOW ALL;" | sed -n \
                -e '/^\(name\|setting\)/{H;$!d}' \
                -e '/./{$!d}' \
                -e 'x' \
                -e '/^\n\?name/s/.*name|\([^\n]*\)\nsetting|\([^\n]*\).*/\1 = \2/p' \
                -e '/^\n\?setting/s/.*setting|\([^\n]*\)\nname|\([^\n]*\).*/\2 = \1/p'
        fi
    ;;
    set)
        declare -a arg=()
        str-split arg "${ARGS[name]}" '=' 2
        name=$(str-trim "${arg[0]}")
        value=$(str-trim "${arg[1]:-}")
        # test that name is valid param name
        psql -v "name=$name" <<< "SELECT current_setting(:'name');" > /dev/null
        sql="ALTER SYSTEM SET :name TO ";
        (( ${#arg[@]} > 1 )) && sql+=":'value';" || sql+="DEFAULT;"
        # shellcheck disable=SC2046
        psql $(verbose-arg -e) -v "name=$name" -v "value=$value" <<< "$sql"
    ;;
esac
