#!/bin/sh

# shellcheck disable=SC1090

# Default display name
DNAME="${SYNOPKG_PKGNAME}"

if [ "$SYNOPKG_DSM_VERSION_MAJOR" -lt 7 ]; then
    # define SYNOPKG_PKGVAR for forward compatibility
    SYNOPKG_PKGVAR="${SYNOPKG_PKGDEST}/var"
fi

# Source package specific variable and functions
SVC_SETUP=$(dirname "$0")"/service-setup"
if [ -r "${SVC_SETUP}" ]; then
    . "${SVC_SETUP}"
fi

# Invoke shell function if available
call_func()
{
    FUNC="$1"
    if type "${FUNC}" 2>/dev/null | grep -q 'function' 2>/dev/null; then
        echo "Begin ${FUNC}" >> "${LOG_FILE}"
        eval "${FUNC}" >> "${LOG_FILE}"
        echo "End ${FUNC}" >> "${LOG_FILE}"
    fi
}

start_daemon()
{
    i=0
    if [ -z "${SVC_QUIET}" ]; then
        if [ -z "${SVC_KEEP_LOG}" ]; then
            date > "${LOG_FILE}"
        else
            date >> "${LOG_FILE}"
        fi
    fi
    call_func "service_prestart"
    printf "%s" "$SERVICE_COMMAND" | while read -r service || [ -n "$service" ]
    do
        i=$((i + 1))
        if [ -z "${SVC_QUIET}" ]; then
            echo "Starting ${DNAME} command ${service}" >> "${LOG_FILE}"
        fi
        if [ -n "${service}" ]; then
            if [ -n "${SVC_NO_REDIRECT}" ]; then
                OUT="/dev/null"
            else
                OUT="${LOG_FILE}"
            fi
            if [ -n "${USER}" ] && [ -n "${SYNOPKG_DSM_VERSION_MAJOR}" ] && [ "$SYNOPKG_DSM_VERSION_MAJOR" -lt 6 ]; then
                # DSM 5 and earlier: use su to switch user context
                # DSM 6+: user is set by conf/privilege, no su needed
                if [ -z "${SVC_CWD}" ]; then
                    SVC_CD=""
                else
                    SVC_CD="cd ${SVC_CWD}; "
                fi
                SU="su ${EFF_USER} -s"
                if [ -z "${SVC_BACKGROUND}" ]; then
                    $SU /bin/sh -c "${SVC_CD}${service}" >> "${OUT}" 2>&1
                else
                    $SU /bin/sh -c "${SVC_CD}${service}" >> "${OUT}" 2>&1 &
                fi
            else
                # DSM 6 user is set by conf/privilege
                if [ -n "${SVC_CWD}" ]; then
                    cd "${SVC_CWD}" || { echo "Failed to cd to ${SVC_CWD}" >> "${LOG_FILE}"; exit 1; }
                fi
                if [ -z "${SVC_BACKGROUND}" ]; then
                    ${service} >> "${OUT}" 2>&1
                else
                    ${service} >> "${OUT}" 2>&1 &
                fi
            fi
            if [ -n "${SVC_WRITE_PID}" ] && [ -n "${SVC_BACKGROUND}" ] && [ -n "${PID_FILE}" ]; then
                [ "$i" -eq 1 ] && printf "%s" "$!" > "${PID_FILE}" || printf " %s" "$!" >> "${PID_FILE}"
            else
                wait_for_status 0 "${SVC_WAIT_TIMEOUT:=20}"
            fi
        fi
    done
}

stop_daemon()
{
    if [ -n "${PID_FILE}" ] && [ -r "${PID_FILE}" ]; then
        for pid in $(cat "${PID_FILE}")
        do
            if [ -z "${SVC_QUIET}" ]; then
                date >> "${LOG_FILE}"
                echo "Stopping ${DNAME} service : $(ps -p "${pid}" -o comm=) (${pid})" >> "${LOG_FILE}"
            fi
            kill -TERM "${pid}" >> "${LOG_FILE}" 2>&1
            wait_for_status 1 "${SVC_WAIT_TIMEOUT:=20}" "${pid}" || kill -KILL "${pid}" >> "${LOG_FILE}" 2>&1
        done
        if [ -f "${PID_FILE}" ]; then
            rm -f "${PID_FILE}" > /dev/null
        fi
    fi
    call_func "service_poststop"
}

#------------------------------------------------------
# daemon_status()
#     $1: PID to check, if empty use ${PID_FILE}
# status: Keeps track of kill -0 exit status
#
# Return 0 when all pid are OK, else return 1
#------------------------------------------------------
daemon_status()
{
    status=0
    [ -z "${1}" ] && pid_list=$(cat "${PID_FILE}" 2>/dev/null) || pid_list="${1}"
    if [ -n "${pid_list}" ]; then
        for pid in ${pid_list}
        do
            kill -0 "${pid}" > /dev/null 2>&1
            status=$((status + $?))
        done
        if [ "$status" -ne 0 ]; then
            rm -f "${PID_FILE}" > /dev/null
            return 1
        else
            return 0
        fi
    else
        return 1
    fi
}

#------------------------------------------------------
# wait_for_status()
#      $1: expected return from daemon_status() call
#      $2: timeout (e.g. number of loop to be done)
#      $3: PID to check being passed to daemon_status()
# counter: Number of 1sec iteration to wait until
#          the return value from daemon_status()
#          match expected value
#
# Wait for a duration of $counter seconds for the
# return value from daemon_status().  If it match
# return 0 else return 1 if wait time is over.
#------------------------------------------------------
wait_for_status()
{
    # default value: 20 seconds
    counter=${2}
    counter="${counter:=20}"
    while [ "${counter}" -gt 0 ]; do
        daemon_status "${3}"
        [ "$?" -eq "$1" ] && return
        counter=$((counter - 1))
        sleep 1
    done
    return 1
}

case $1 in
    start)
        if daemon_status; then
            echo "${DNAME} is already running" >> "${LOG_FILE}"
            exit 0
        else
            echo "Starting ${DNAME} ..." >> "${LOG_FILE}"
            start_daemon
            exit $?
        fi
        ;;
    stop)
        if daemon_status; then
            echo "Stopping ${DNAME} ..." >> "${LOG_FILE}"
            stop_daemon
            exit $?
        else
            echo "${DNAME} is not running" >> "${LOG_FILE}"
            exit 0
        fi
        ;;
    status)
        if daemon_status; then
            echo "${DNAME} is running"
            exit 0
        else
            echo "${DNAME} is not running"
            exit 3
        fi
        ;;
    log)
        # log output for DSM < 6
        if [ -n "${LOG_FILE}" ] && [ -r "${LOG_FILE}" ]; then
            # Shorten long logs to last 100 lines
            TEMP_LOG_FILE="${SYNOPKG_PKGVAR}/${SYNOPKG_PKGNAME}_temp.log"
            # Clear any previous log
            echo "Full log: ${LOG_FILE}" > "${TEMP_LOG_FILE}"
            tail -n100 "${LOG_FILE}" >> "${TEMP_LOG_FILE}"
            echo "${TEMP_LOG_FILE}"
        fi
        exit 0
        ;;
    *)
        exit 1
        ;;
esac
