#!/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 || \
    bb_fatal "could not load bash-ini lib"

SESSION_PID=

function is_session_running() {
    if [ -z "$SESSION_PID" ]
    then
        return 1
    else
        if kill -0 "$SESSION_PID"
        then
            return 0
        else
            SESSION_PID=
            return 1
        fi
    fi
}

# function create_lightdm_config() {
#     local _user="$1"

#     cat <<EOF
# [LightDM]
# minimum-vt=1
# lock-memory=true
# user-authority-in-system-dir=true
# sessions-directory=/usr/local/share/xsessions-locallab

# [Seat:*]
# xserver-command=X -background none
# greeter-session=lightdm-gtk-greeter
# greeter-hide-users=true
# user-session=xfce
# session-wrapper=/etc/X11/xinit/Xsession
# autologin-guest=false
# autologin-user=$_user
# autologin-user-timeout=0
# # greeter-setup-script=/usr/local/sbin/lightdm-greeter-setup-hook
# session-wrapper=/usr/sbin/exam-env-xsession-wrapper
# session-setup-script=/usr/sbin/exam-env-call-hook lightdm-session-setup.sh
# session-cleanup-script=/usr/sbin/exam-env-call-hook lightdm-session-cleanup.sh

# [XDMCPServer]

# [VNCServer]


# EOF
# }

function kill_session() {
    if is_session_running
    then
        echo "kill_session: kill $SESSION_PID" >&2
        kill "$SESSION_PID"
        killall lightdm
        # enhancement options:
        # do we want to wait until it is stopped or retry with -KILL
    else
        echo "kill_session: no session detected" >&2
    fi
}

# function switch_to_lightdm() {
#     systemctl start lightdm
#     bb_msg info "quitting and launching lightdm"
#     systemctl stop rclogind
# }

function cmd_login() {
    (( $# == 1 )) || {
        bb_msg err "cmd_login: expected 1 arg but got $#"
        return 1
    }

    local _user="$1"

    id -u "$_user" >/dev/null || {
        bb_msg err "cmd_login: no such user: $_user"
        return 2
    }

    if is_session_running
    then
        bb_msg err "cmd_login: session already running"
        return 3
    fi

    echo "NOW LOGGING IN USER $_user" >&2

    #    # start X session for user
    #    su --login "$_user" startx /bin/mate-session &

    # create_lightdm_config "$_user" > /etc/loginrc-lightdm.conf
    # lightdm --config=/etc/loginrc-lightdm.conf -d 2>/dev/null >/2 &

    mkdir -p /etc/dmal
    echo "$_user" > /etc/dmal/autologin-user
    dmald &

    SESSION_PID="$!"
    echo "cmd_login: SESSION_PID=$SESSION_PID" >&2
}

function cmd_logout() {
    kill_session
    sleep 1
    chvt 7
}

function check_for_cmd() {
    local _cmd_file="/var/run/rclogind/cmd"

    if [ -f "$_cmd_file" ]
    then
        local -a _cmd
        read -r -a _cmd < "$_cmd_file"

        (( ${#_cmd[@]} > 0 )) || {
            bb_msg err "check_cmd: got empty cmd"
            rm -f "$_cmd_file"
            return 0
        }

        [[ "${_cmd[0]}" =~ ^(login)|(logout)$ ]] || {
            bb_msg err "check_cmd: got unknowen cmd: ${_cmd[0]}"
            rm -f "$_cmd_file"
            return 0
        }

        "cmd_${_cmd[0]}" "${_cmd[@]:1}" || \
            bb_msg err "check_cmd: failed to execute command: ${_cmd[*]}"

        rm -f "$_cmd_file"
    fi
}

function getconfig() {
    [[ -f "$1" ]] && \
        bini_db_load rclogindconf "$1"

    bini_get_value WAITMSG rclogindconf waitmsg || \
        WAITMSG="rclogind waiting for events"

    if bini_get_value DISPLAYNAME rclogindconf displayname
    then
        DISPLAYNAME=" | $DISPLAYNAME"
    else
        DISPLAYNAME=""
    fi

    local boxesargsstr
    bini_get_value boxesargsstr rclogindconf boxesargs || \
        boxesargsstr=""

    ## currently no spaces are supported in arguments, so exit if they
    ## are enforced with " or '
    if [[ $boxesargsstr == *"'"* ]] || [[ $boxesargsstr == *'"'* ]]
    then
        bb_msg info "boxesargs may not contain ' or \""
        boxesargsstr=""
    fi

    ## remove dangerous characters
    boxesargsstr=${boxesargsstr//;/}
    boxesargsstr=${boxesargsstr//&/}

    [[ -n $boxesargsstr ]] || \
        boxesargsstr="-d inf2tuxthink -f /usr/share/boxes/inf2_boxes -p h10v2"

    bb_string_split BOXESARGS "$boxesargsstr" " "
}

function main() {
    echo "starting up" >&2

    # make us active virtual terminal
    chvt 7

    # unblock screen and disable blanking of virtual terminal
    setterm -blank poke
    setterm -blank 0

    # disable ctrl-c
    trap : INT

    # exit gracefully if stopped e.g. by systemd
    trap "chvt 1; bb_quit 0 terminated" TERM

    mkdir -p /var/run/rclogind

    # get config from config file or set default values
    declare -a BOXESARGS
    declare -g DISPLAYNAME WAITMSG
    getconfig "/etc/rclogind.conf"

    local _key
    local -i _now _lastm=0

    while true
    do
        printf -v _now "%(%s)T" -1

        # redraw the whole screen every minute
        if (( _now >= _lastm+60 ))
        then
            _lastm="$_now"

            # clear screen
            clear

            # go a little down for tux thinking
            tput cup 15 0

            # let tux think what host it is sitting on
            figlet -f mono12 -t -c "${HOSTNAME%%.*}" | \
                head -n -1 | \
                cut -c 12- | \
                boxes "${BOXESARGS[@]}"
        fi

        # go to top and erase first line, otherwise long dates may leave
        # artefacts when followed by short dates
        tput cup 0 0
        tput el

        # write current date, displayname and wait line msg
        printf \
            "%(%A, %e %B %Y - %H:%M:%S)T | %s%s\n%s " \
            -1 "${HOSTNAME//.tuwien.ac.at}" "${DISPLAYNAME:-}" "$WAITMSG"

        check_for_cmd

        # read input, but do not print it on screen, ignore everything
        # except Q and L
        if read -r -t 1 -N 1 -s _key
        then
            # lets disable keys for now until we make this configurable
            if false
            then
                case "$_key" in
                    Q ) chvt 1
                        bb_quit 0 "quitting on users request"
                        ;;
                    L ) switch_to_lightdm;;
                esac
            fi
        else
            if (( $? > 128 ))
            then
                # timeout
                continue
            else
                bb_quit 1 "got EOF from stdin"
            fi
        fi
    done
}

main "$@"
bb_quit 0
