#!/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/optparser.bash"
source "$SCRIPT_DIR/lib/verbose.bash"
source "$SCRIPT_DIR/lib/str.bash"

readonly -A PathAlias=(
    [vbr]="veeam_backup_and_replication.conf"
    [vbem]="veeam_backup_reporting.conf"
    [catalog]="veeam_backup_catalog.conf"
    [distribution]="veeam_distribution_service.conf"
    [threat-hunter]="veeam_threat_hunter.conf"
    [mount]="veeam_mount_service.conf"
)

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

optparser-init op \
    --desc "Show or modify Veeam Backup settings."
optparser-addopt op --name "command" --narg 1 \
    --add-choice "get" \
    --add-choice "set" \
    --add-choice "del" \
    --help "command to interact with configuration settings."
optparser-addopt op --name "regpath" --narg 1 \
    --help "registry path to option"
optparser-addopt op --name "value" --narg '?' \
    --help "value to set"
optparser-addopt op -s "-c" -l "--conf" --narg 1 \
    --default "/etc/veeam" \
    --help "root file or root directory for registry path"
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; }

trap-init

regpath=$(realpath -m "/${ARGS[regpath]//\\//}")
regpath=${regpath/#\//}

if [[ -d ${ARGS[conf]} ]]; then
    regpath=${regpath/#HKLM/HKEY_LOCAL_MACHINE}
    regpath=${regpath#HKEY_LOCAL_MACHINE/Software/Veeam/}
    tmp=()
    str-split tmp "$regpath" '/' 2
    if [[ -z "${tmp[0]:-}" ]]; then
        die "failed to detect configuration file"
    elif [[ -n ${PathAlias[${tmp[0]@L}]:-} ]]; then
        file="${ARGS[conf]}/${PathAlias[${tmp[0]@L}]:-}"
    else
        file=${tmp[0]// /_}
        file="${ARGS[conf]}/${file@L}.conf"
    fi
    regpath=${tmp[1]:-}
    unset tmp
elif [[ -f ${ARGS[conf]} ]]; then
    file="${ARGS[conf]}"
else
    die "${ARGS[conf]}: no such file or directory"
fi

if [[ ${ARGS[regpath]} = */ ]]; then
    section=${regpath:-.}
    key=
else
    section=$(dirname "$regpath")
    key=$(basename "$regpath")
fi
if [[ $section = '.' ]]; then
    section=root
    nosection=1
else
    nosection=
fi


case ${ARGS[command]} in
    get)
        [[ -f $file ]] || exit 0
        [[ -r $file ]] || die "$file: permission denied"
        [[ -n $key ]] || exit 0 # temperary unsupported
        include=()
        if [[ -d "${file}.d" ]]; then
            mapfile -t include < <(find "${file}.d" -maxdepth 1 -type f -name "*.conf")
        fi
        section=${section//\//\\\\} # double \\ for awk
        if [[ -n $key ]]; then
            awk -f "$SCRIPT_DIR/lib/cfgfile.awk" \
                -v "s_lc=${section@L}" -v "k_lc=${key@L}" \
                -e 'BEGIN { section = section_lc = "root" }' \
                -e 'section_lc == s_lc && key_lc == k_lc {result = value}' \
                -e 'END { if (result) print result }' \
                "$file" "${include[@]}"
        else
            # temperary unsupported
            awk -f "$SCRIPT_DIR/lib/cfgfile.awk" \
                -v "s_lc=${section@L}" \
                -e 'BEGIN { FNUM=0; section = section_lc = "root"; }' \
                -e 'FNR == 1 { FNUM++; }' \
                -e 'section_lc == s_lc {
                        if (FNUM != 1 && ltype == "section")
                            print "#", FILENAME;
                        print $0;
                }' \
                "$file" "${include[@]}"
        fi
    ;;
    set)
        [[ -n $key ]] || die "${ARGS[regpath]}: no option name found"
        case ${key@L} in
            *password*|*passwd*)
                verbose-echo "$file: [$section] write $key=***"
                ;;
            *)
                verbose-echo "$file: [$section] write $key=${ARGS[value]:-}"
                ;;
        esac
        if [[ ! -f $file ]]; then
            [[ -w $(dirname "$file") ]] || die "$file: permission denied"
            section=${section//\//\\}
            [[ -n $nosection ]] || echo "[$section]" >> "$file"
            echo "$key=${ARGS[value]:-}" >> "$file"
            exit 0
        fi
        [[ -w $file ]] || die "$file: permission denied"
        section=${section//\//\\\\} # double \\ for awk
        awk -f "$SCRIPT_DIR/lib/cfgfile.awk" \
            -v "s=${section}" -v "k=${key}" -v "v=${ARGS[value]:-}" \
            -v "s_lc=${section@L}" -v "k_lc=${key@L}" \
            -v "nosection=$nosection" \
            -e 'BEGIN { section = section_lc = "root"; inflag = nosection; }' \
            -e 'section_lc == s_lc && key_lc == k_lc { $0 = key"="v; done = 1; }' \
            -e 'section_lc == s_lc && ltype == "section" { inflag = 1; }' \
            -e 'section_lc != s_lc && ltype == "section" {
                    if (inflag && !done) {
                        print k"="v;
                        done = 1;
                    }
                    inflag = 0;
                }' \
            -e 'ltype == "empty" { ebuf[ibuf++] = $0 }' \
            -e 'ltype != "empty" {
                    for (i = 0; i < ibuf; i++) print ebuf[i];
                    ibuf = 0;
                    print $0;
                }' \
            -e 'END {
                    if (inflag && !done) {
                        print k"="v;
                        done = 1;
                    }
                    for (i = 0; i < ibuf; i++) print ebuf[i];
                    if (!done) {
                        if (ibuf == 0 && NR > 0) { printf "\n"; }
                        print "["s"]"
                        print k"="v
                    }
                }' \
            -i inplace "$file"
    ;;
    del)
        [[ -n $key ]] || die "${ARGS[regpath]}: no option name found"
        verbose-echo "$file: [$section] delete $key"
        [[ -f $file ]] || exit 0
        [[ -w $file ]] || die "$file: permission denied"
        section=${section//\//\\\\} # double \\ for awk
        awk -f "$SCRIPT_DIR/lib/cfgfile.awk" \
            -v "s_lc=${section@L}" -v "k_lc=${key@L}" \
            -e 'BEGIN { section = section_lc = "root"; }' \
            -e 'section_lc != s_lc || key_lc != k_lc { print $0; }' \
            -i inplace "$file"
    ;;
esac
