#!/usr/bin/bash

# source bash base library
# shellcheck disable=SC1091
source /usr/libexec/bash-base.bash || {
        echo "$0: fatal error: failed to source /usr/libexec/bash-base.bash" >&2
        exit 1
}

bb_require_libs bash-ini ldapusermgmt/common

# shellcheck disable=SC2120,SC2034
function local_usage() {
    usage "${1-1}" "${2-}" "add <name>" "del <name>" "deltree <name>" \
        "list" <<EOF
  Removes on or more users specified on command line or read from pipe not
  connected to a terminal.
EOF
}

function subhier_add() {
    (( $# == 1 )) || bb_fatal "subhier_add expects 1 arg but got $#"
    SUBHIER_NAME="$1"

    ldap_cmd write ldapadd <<EOF || \
        bb_quit 1 "failed to add subhier: $SUBHIER_NAME"
dn: ou=$SUBHIER_NAME,${LDAP_USER_SUBHIER},${LDAP_SEARCH_BASE}
ou: $SUBHIER_NAME
objectClass: organizationalUnit

dn: ou=$SUBHIER_NAME,${LDAP_GROUP_SUBHIER},${LDAP_SEARCH_BASE}
ou: $SUBHIER_NAME
objectClass: organizationalUnit

dn: ou=$SUBHIER_NAME,${LDAP_AUTOFS_HOMES},${LDAP_AUTOFS_SUBHIER},${LDAP_SEARCH_BASE}
ou: $SUBHIER_NAME
objectClass: organizationalUnit
EOF
}

# subhier_del
# deletes empty subhiers
function subhier_del() {
    (( $# == 1 )) || bb_fatal "subhier_del expects 1 but got $# args"

    local _ou="$1"

    ldap_cmd write ldapdelete -c \
        "ou=$_ou,${LDAP_USER_SUBHIER},${LDAP_SEARCH_BASE}" \
        "ou=$_ou,${LDAP_GROUP_SUBHIER},${LDAP_SEARCH_BASE}" \
        "ou=$_ou,${LDAP_AUTOFS_HOMES},${LDAP_AUTOFS_SUBHIER},${LDAP_SEARCH_BASE}" \
        || bb_quit 1 "failed to delete subhier (maybe not empty?): $_ou"
}

# _expand_homedir_helper <homedir> <index>
# modifies vars: shdel__home_hosts _home_paths
function _expand_homedir_helper() {
    (( $# == 2 )) || \
        bb_fatal "_expand_homedir_helper called with $# instead of 2 args"

    local _homedir="$1"
    local _index="$2"

    if [[ "$_homedir" =~ : ]]
    then
        shdel__home_hosts[_index]="${_homedir%%:*}"
        shdel__home_paths[_index]="${_homedir#*:}"
    else
        shdel__home_hosts[_index]="localhost"
        shdel__home_paths[_index]="$_homedir"
    fi
}

# shdel_process_host <host>
# shellcheck disable=SC2034
function shdel_process_host() {
    (( $# == 1 )) || \
        bb_fatal "shdel_process_host called with $# instead of 1 arg"

    local _host="$1"

    local DEL_MUL_NAME="SUBHIER-$_ou"

    # FIXME: HOMEDIR_HOST_EXTRA_PATHS should better be an array
    # shellcheck disable=SC2206
    local -a DEL_MUL_EXTRA_PATHS=($HOMEDIR_HOST_EXTRA_PATHS)

    # FIXME: BACKUP_EXCLUDE_PATHS should better be an array
    # shellcheck disable=SC2206
    local -a BACKUP_EXCLUDE_PATHS=(${BACKUP_EXCLUDE_PATHS-})

    local -a DEL_MUL_CNS DEL_MUL_HOMEDIRS
    local -i _i

    # filter all users that reside on this host
    for _i in "${!shdel__uids[@]}"
    do
        if [ "${shdel__home_hosts[$_i]}" == "$_host" ]
        then
            DEL_MUL_CNS[_i]="${shdel__uids[$_i]}"
            DEL_MUL_HOMEDIRS[_i]="${shdel__home_paths[$_i]}"
        fi
    done

    homedir_host_helper "$_host" delete_multiple_userdata \
        HOMEDIR_BACKUP_PATH BACKUP_EXCLUDE_PATHS \
        DEL_MUL_NAME DEL_MUL_CNS DEL_MUL_HOMEDIRS DEL_MUL_EXTRA_PATHS
}

# subhier_deltree
# deletes subhiers including all users
function subhier_deltree() {
    (( $# == 1 )) || bb_fatal "subhier_del expects 1 but got $# args"

    local _ou="$1"

    [ -n "${LDAP_ONLY-}" ] || {
        local -a shdel__uids
        ldap_extract_attributes "uid" shdel__uids < \
            <(ldap_cmd read ldapsearch -LLL -z 0 \
            -b "ou=$_ou,${LDAP_USER_SUBHIER},${LDAP_SEARCH_BASE}" \
            objectclass=account uid || true)

        local -i _retval=0
        bb_array_is_empty shdel__uids || _retval="$?"
        (( _retval == 91 )) || {
            bb_msg info "deltree: subhier '$_ou' seems to be empty," \
                "redirecting to del"
            subhier_del "$_ou"
            return $?
        }

        bb_msg info "deltree users: ${shdel__uids[*]}"

        local -a shdel__homedirs
        bb_array_map shdel__homedirs shdel__uids \
            ldap_resolve_user_homedir || {
            local _ret="$?"
            if (( _ret == 91 ))
            then
                bb_msg err "failed to resolv homedirs of some users"
            else
                bb_quit 1 "internal error while resolving homedirs of users"
            fi
        }

        bb_msg info "deltree homedirs: ${shdel__homedirs[*]}"

        # shellcheck disable=SC2034
        local -a shdel__home_hosts shdel__home_paths
        bb_array_iter_i shdel__homedirs _expand_homedir_helper

        local -a shdel__home_hosts_unique
        bb_array_unique shdel__home_hosts_unique \
            shdel__home_hosts

        bb_msg info "deltree unique hosts: ${shdel__home_hosts_unique[*]}"


        local -a shdel__current_host
        for shdel__current_host in "${shdel__home_hosts_unique[@]}"
        do
            bb_msg info "deltree: now working on host $shdel__current_host"
            shdel_process_host "$shdel__current_host"
        done
    }

    # shellcheck disable=SC2034
    local -a LDAP_LOCAL_ARGS=("-r")

    ldap_cmd write ldapdelete -c \
        "ou=$_ou,${LDAP_USER_SUBHIER},${LDAP_SEARCH_BASE}" \
        "ou=$_ou,${LDAP_GROUP_SUBHIER},${LDAP_SEARCH_BASE}" \
        "ou=$_ou,${LDAP_AUTOFS_HOMES},${LDAP_AUTOFS_SUBHIER},${LDAP_SEARCH_BASE}"
}

function subhier_list() {
    (( VERBOSITY < 2 )) || echo -e 'EXTRA-SUBHIER\tPARENT-SUBHIERS'
    {
        ldap_cmd read ldapsearch -Q -LLL -s children \
            -b "${LDAP_USER_SUBHIER},${LDAP_SEARCH_BASE}" \
            'objectClass=organizationalUnit' dn || \
            bb_fatal "subhier_list: ldapsearch failed";
        ldap_cmd read ldapsearch -Q -LLL -s children \
            -b "${LDAP_GROUP_SUBHIER},${LDAP_SEARCH_BASE}" \
            'objectClass=organizationalUnit' dn || \
            bb_fatal "subhier_list: ldapsearch failed";
        ldap_cmd read ldapsearch -Q -LLL -s children \
            -b "${LDAP_AUTOFS_HOMES},${LDAP_AUTOFS_SUBHIER},${LDAP_SEARCH_BASE}" \
            'objectClass=organizationalUnit' dn || \
            bb_fatal "subhier_list: ldapsearch failed";
    } | awk -F, '/^dn: / {gsub("dn: ",""); gsub("ou=","",$1); hash[$1] = sprintf( "%s %s", hash[$1], $2)} END { for (key in hash) { printf "%s\t\t%s\n", key, hash[key] }}' \
        | sort
}

function main() {
    # shellcheck disable=SC2119
    (( $# > 0 )) || local_usage 1 "Missing mandatory argument"

    config_init

    local _op="$1"
    shift
    case "$_op" in
        add) subhier_add "$@";;
        del) subhier_del "$@";;
        deltree)
            if [ -z "${FORCE-}" ]
            then
                [ -t 0 ] || bb_quit 1 "deltree required force" \
                    "or interactive terminal on stdin to ask"
                bb_msg alert 'THIS WILL DELETE THE WHOLE SUBTREE!'
                bb_msg alert 'enter to continue, ctrl-c to abort'
                read -r || bb_quit 1 "aborted on users request"
            fi
            subhier_deltree "$@";;
        list) subhier_list;;
        *) local_usage 1 "illegal argument: $_op";;
    esac
}

parse_common_args main "" "" "$@"
bb_quit
