#!/bin/sh
#
# Copyright (C) 2020-2022 dudemanguy@artixlinux.org
# Copyright (C) 2022 artoo@artixlinux.org
# Copyright (C) 2022 Artix Linux Developers
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

#!/sh/hint

#{{{ common

check_root() {
    [ "$(id -u)" = 0 ] && return
    if [ -f /usr/bin/sudo ]; then
        # shellcheck disable=SC2086
        exec sudo -- "$0" ${OPTS}
    else
        # shellcheck disable=2154
        exec su root -c "$0 ${OPTS}"
    fi
}

# }}}

#!/sh/hint

#{{{ color

colorize() {
    # prefer terminal safe colored and bold text when tput is supported
    if tput setaf 0 >/dev/null; then
        ALL_OFF="$(tput sgr0)"
        BOLD="$(tput bold)"
        BLUE="${BOLD}$(tput setaf 4)"
        GREEN="${BOLD}$(tput setaf 2)"
        RED="${BOLD}$(tput setaf 1)"
        YELLOW="${BOLD}$(tput setaf 3)"
        WHITE="${BOLD}$(tput setaf 7)"
    else
        ALL_OFF="\e[0m"
        BOLD="\e[1m"
        BLUE="${BOLD}\e[34m"
        GREEN="${BOLD}\e[32m"
        RED="${BOLD}\e[31m"
        YELLOW="${BOLD}\e[33m"
        WHITE="${BOLD}\e[37m"
    fi
    readonly ALL_OFF BOLD BLUE GREEN RED YELLOW WHITE
}

if [ -t 2 ] && [ "$TERM" != dumb ]; then
    colorize
else
    # shellcheck disable=2034
    ALL_OFF='' BOLD='' BLUE='' GREEN='' RED='' YELLOW=''
fi

msg(){
    mesg=$1; shift
    # shellcheck disable=2059
    printf "${WHITE} ${mesg}${ALL_OFF}\n" "$@"
}

error(){
    mesg=$1; shift
    # shellcheck disable=2059
    printf "${RED} ERROR:${ALL_OFF} ${WHITE}${mesg}${ALL_OFF}\n" "$@"
    exit 1
}

# }}}

#{{{ table

row_header(){
    mesg=$1; shift
    # shellcheck disable=2059
    printf "${BLUE} ${mesg} ${ALL_OFF}\n" "$@"
}

row_up(){
    mesg=$1; shift
    # shellcheck disable=2059
    printf "${GREEN} ${mesg}${ALL_OFF}\n" "$@"
}

row_down(){
    mesg=$1; shift
    # shellcheck disable=2059
    printf "${RED} ${mesg}${ALL_OFF}\n" "$@"
}

row_dep(){
    mesg=$1; shift
    # shellcheck disable=2059
    printf "${WHITE} |__${mesg}${ALL_OFF}\n" "$@"
}

#}}}


#{{{ func

convert_t () {
    secs="$1"
    if [ "$secs" -eq 0 ]; then
        printf "0:00:00:00\n"
    else
        date -d "@$secs" "+$((secs/86400)):%H:%M:%S"
    fi
}

is_bundle() {
    for bundle in $(s6-rc-db list bundles); do
        if [ "$bundle" = "$BUNDLE" ]; then
            return 0
        fi
    done
    return 1
}

#}}}

show_bundle() {
    if ! is_bundle; then
        error "Bundle (%s) does not exist!" "$BUNDLE"
    fi

    msg "Bundle: %s" "$BUNDLE"
    row_header "$table" "service" "type" "pid" "time" "up"

    for sv in $(s6-rc-db contents "$BUNDLE"); do
        _type=''
        _type=$(s6-rc-db type "${sv}")
        if [ "$_type" = 'longrun' ]; then
            _stat='' _pid='' _time=''
            _stat=$(s6-svstat -u "${SVDIRS}/$sv")
            _pid=$(s6-svstat -o pid "${SVDIRS}/$sv")
            _time=$(s6-svstat -t "${SVDIRS}/$sv")
            if "$_stat"; then
                row_up "$table" "$sv" "$_type" "$_pid" "$(convert_t "$_time")" "$_stat"
            else
                row_down "$table" "$sv" "$_type" "$_pid" "$(convert_t "$_time")" "$_stat"
            fi
            if [ "$DEPS" -eq 1 ]; then
                for d in $(s6-rc-db dependencies "$sv"); do
                    _type=$(s6-rc-db type "$d")
                    if [ "$_type" = 'longrun' ]; then
                        _stat=$(s6-svstat -u "${SVDIRS}/$d")
                        _pid=$(s6-svstat -o pid "${SVDIRS}/$d")
                        _time=$(s6-svstat -t "${SVDIRS}/$d")
                        row_dep "$dtable" "$d" "$_type" "$_pid" "$(convert_t "$_time")" "$_stat"
                    elif [ "$_type" = 'oneshot' ]; then
                        row_dep "$dtable" "$d" "$_type" "" "" ""
                    fi
                done
            fi
        fi
    done
}

usage() {
    printf 'Usage: %s [options] [optional bundle name]\n' "${0##*/}"
    printf '          Default Bundle: [default]\n'
    printf '\n'
    printf ' -d       Show service dependencies\n'
    printf ' -h       This help\n'
    printf '\n'
    exit "$1"
}

OPTS="$*"

DEPS=0

RUNPATH='/run/s6-rc'

SVDIRS="${RUNPATH}/servicedirs"

readonly table="%-70s %-10s %-10s %-14s %-5s"
readonly dtable="%-67s %-10s %-10s %-14s %-5s"

while getopts :dh arg; do
    case "${arg}" in
        d) DEPS=1 ;;
        h|?) usage 0 ;;
    esac
done
shift $(( OPTIND - 1 ))

BUNDLE=${1:-default}

check_root

show_bundle
