#!/bin/sh

po_domain="alterator-ahttpd"
alterator_api_version=1

# TODO: Support systemd timers
cron_file=/etc/cron.d/alterator-ahttpd
mail_conf=/etc/state-change-notify/mail.conf

. alterator-sh-functions
. alterator-service-functions

can_shutdown=no; shutdown_cmd=
can_reboot=no; reboot_cmd=
can_suspend=no; suspend_cmd=
can_hibernate=no; hibernate_cmd=

init()
{
    if sd_avail; then
        shutdown_cmd="/sbin/systemctl poweroff"
        reboot_cmd="/sbin/systemctl reboot"
        suspend_cmd="/sbin/systemctl suspend"
        hibernate_cmd="/sbin/systemctl hibernate"
    else
        shutdown_cmd="/sbin/shutdown -t 3 -h now"
        reboot_cmd="/sbin/shutdown -t 3 -r now"

        if [ -x /usr/sbin/pm-suspend ]; then
            suspend_cmd="/usr/sbin/pm-suspend"
        fi

        if [ -x /usr/sbin/pm-hibernate ]; then
            hibernate_cmd="/usr/sbin/pm-hibernate"
        fi
    fi

    if [ -n "$shutdown_cmd" ]; then
        can_shutdown=yes
    fi
    if [ -n "$reboot_cmd" ]; then
        can_reboot=yes
    fi
    if [ -n "$suspend_cmd" ]; then
        can_suspend=yes
    fi
    if [ -n "$hibernate_cmd" ]; then
        can_hibernate=yes
    fi
}

read_cron_time()
{
    local cron_file="$1"

    [ ! -s "$cron_file" ] ||
	while read min hour monthday month weekday rest;do
	    [ -n "${min%\#*}" ] || continue

	    echo "$hour:$min:00"
	    return
	done <"$cron_file"
}

read_cron()
{
    local cron_file="$1"
    local state="$2"

    local cron_time="$(read_cron_time "$cron_file")"
    write_string_param "${state}_time" "${cron_time:-23:00:00}"

    if service_exists crond && \
       service_control crond is-active && \
       [ -s "$cron_file" ]
    then
        write_bool_param "${state}_cron" 'yes'
    else
        write_bool_param "${state}_cron" 'no'
    fi
}

write_cron()
{
    local cron_file="$1"
    local state="$2"
    local cron_flag="$3"
    local cron_time="$4"
    local cmd="$5"

    if [ -n "$cmd" ] && test_bool "$cron_flag" && [ -n "$cron_time" ]
    then
	    local time="${cron_time%:*}"
	    local hour="${time%:*}"
	    local min="${time#*:}"
	    printf '%s %s * * * root %s\n' "$min" "$hour" "$cmd" >"$cron_file"
    else
	    rm -f "$cron_file"
    fi

    touch "$(dirname "$cron_file")"
}

reboot()
{
    [ -n "$reboot_cmd" ] && $reboot_cmd >&2
}

poweroff()
{
    [ -n "$shutdown_cmd" ] && $shutdown_cmd >&2
}

suspend()
{
    [ -n "$suspend_cmd" ] && $suspend_cmd >&2
}

hibernate()
{
    [ -n "$hibernate_cmd" ] && $hibernate_cmd >&2
}

read_shell_var()
{
    sed -n -e "/^[[:space:]]*$1=[^[:space:]]\\+/ { s/^[[:space:]]*$1=\\([^[:space:]]\\+\\).*\$/\\1/; h }" -e '$ { g; p }' "$2"
}

read_shell_comment()
{
    sed -n -e "/^[[:space:]]*#[#[:space:]]*$1=[^[:space:]]\\+/ { s/^[[:space:]]*#[[:space:]]*$1=\\([^[:space:]]\\+\\).*\$/\\1/; h }" -e '$ { g; p }' "$2"
}

space_values()
{
    echo "$1" | sed -e 's/,\+/ /g;' -e 's/^[[:space:]]\+/ /g;' \
                    -e 's/^ //;' -e 's/ $//;'
}

read_email()
{
    if [ -e "$mail_conf" ]; then
        local email_addr="$(read_shell_var EMAIL_ADDRESS "$mail_conf")"
        if [ -n "$email_addr" ]; then
            email_addr="$email_addr,$(read_shell_var EMAIL_CC_ADDRESS "$mail_conf"),$(read_shell_var EMAIL_BCC_ADDRESS "$mail_conf")"
            email_addr="$(space_values "$email_addr")"
            write_bool_param 'notify_email' 'yes'
            write_string_param 'email_addr' "$email_addr"
        else
            write_bool_param 'notify_email' 'no'
            email_addr="$(read_shell_comment EMAIL_ADDRESS "$mail_conf"),$(read_shell_var EMAIL_CC_ADDRESS "$mail_conf"),$(read_shell_comment EMAIL_CC_ADDRESS "$mail_conf"),$(read_shell_var EMAIL_BCC_ADDRESS "$mail_conf"),$(read_shell_comment EMAIL_BCC_ADDRESS "$mail_conf")"
            email_addr="$(space_values "$email_addr")"
            if [ -n "$email_addr" ]; then
                write_string_param 'email_addr' "$email_addr"
            else
                write_string_param 'email_addr' ""
            fi
        fi
    else
        write_bool_param 'notify_email' 'no'
        write_string_param 'email_addr' ""
    fi
}

comma_values()
{
    echo "$1" | sed -e 's/^[[:space:]]\+/ /g;' -e 's/^ //;' \
                    -e 's/ $//;' \
                    -e 's/ *, */,/g' \
                    -e 's/ /,/g;'
}

write_shell_var()
{
    sed -i -e "/^[#[:space:]]*$1=/ { s/^[#[:space:]]*$1=.*\$/$1=$2/; b exit }" \
           -e 'p; d' \
           -e "\$ { s/^.*\$/&\n$1=$2/; }" \
           -e ':exit n; b exit' \
        "$3"
}

write_shell_comment()
{
    sed -i -e "/^[#[:space:]]*$1=/ { s/^[#[:space:]]*$1=.*\$/#$1=$2/; b exit }" \
           -e 'p; d' \
           -e "\$ { s/^.*\$/&\n#$1=$2/; }" \
           -e ':exit n' \
           -e "s/^[[:space:]]*$1=/#&/" \
           -e 'b exit' \
        "$3"
}

write_email()
{
    if [ -n "$in_email_addr" ]; then
        local email_addr="$(comma_values "$in_email_addr")"

        local email_cc_addr="${email_addr#*,}"
        email_addr="${email_addr%%,*}"

        if [ "$email_addr" = "$email_cc_addr" ]; then
            email_cc_addr=
        fi

        if test_bool "$in_notify_email"; then
            write_shell_var EMAIL_ADDRESS "$email_addr" "$mail_conf"
            write_shell_var EMAIL_CC_ADDRESS "$email_cc_addr" "$mail_conf"
            write_shell_var EMAIL_BCC_ADDRESS "" "$mail_conf"
        else
            write_shell_comment EMAIL_ADDRESS "$email_addr" "$mail_conf"
            write_shell_comment EMAIL_CC_ADDRESS "$email_cc_addr" "$mail_conf"
            write_shell_comment EMAIL_BCC_ADDRESS "" "$mail_conf"
        fi
    fi
}

read_power()
{
    write_bool_param 'can_shutdown' "$can_shutdown"
    read_cron "$cron_file" 'shutdown'

    write_bool_param 'can_reboot' "$can_reboot"
    read_cron "${cron_file}-reboot" 'reboot'

    write_bool_param 'can_suspend' "$can_suspend"
    read_cron "${cron_file}-suspend" 'suspend'

    write_bool_param 'can_hibernate' "$can_hibernate"
    read_cron "${cron_file}-hibernate" 'hibernate'

    read_email "$@"

    if service_exists state-change-notify-postfix; then
        write_bool_param 'email_available' 'yes'
    else
        write_bool_param 'email_available' 'no'
    fi
}

write_power()
{
    write_cron "$cron_file" 'shutdown' "$in_shutdown_cron" \
               "$in_shutdown_time" "$shutdown_cmd"

    write_cron "${cron_file}-reboot" 'reboot' "$in_reboot_cron" \
               "$in_reboot_time" "$reboot_cmd"

    write_cron "${cron_file}-suspend" 'suspend' "$in_suspend_cron" \
               "$in_suspend_time" "$suspend_cmd"

    write_cron "${cron_file}-hibernate" 'hibernate' "$in_hibernate_cron" \
               "$in_hibernate_time" "$hibernate_cmd"

    local cron_status=0
    if service_exists crond; then
        if ! service_control crond is-active; then
            service_control crond enable-start || \
                    cron_status=$?
            service_control crond is-active || \
	            cron_status=$?
        fi
    else
        cron_status=255
    fi

    if [ $cron_status -ne 0 ]; then
        write_error "$(_ 'Unable to configure "crond" service!')"
    fi

    if service_exists state-change-notify-postfix; then
        write_email "$@"
        if test_bool "$in_notify_email"; then
            service_control state-change-notify-postfix enable-start
        else
            service_control state-change-notify-postfix disable-stop
        fi
    fi
}

init

alterator_export_var  shutdown_time time
alterator_export_var  reboot_time time
alterator_export_var  suspend_time time
alterator_export_var  hibernate_time time
alterator_export_var  email_addr e-mail
alterator_export_proc read_power
alterator_export_proc write_power
alterator_export_proc reboot
alterator_export_proc poweroff
alterator_export_proc suspend
alterator_export_proc hibernate

message_loop
