#!/bin/sh
# The application is alive even when the user intentionally disconnects NPC.
# No extra HTTP listener: fnOS continues to authenticate and serve the CGI.
. "$(dirname "$0")/paths"
SELF="${INSTALL_DIR}/scripts/application"
APP_PID="${VAR_DIR}/application.pid"
APP_LOCK="${VAR_DIR}/application.lock"
APP_STOP="${VAR_DIR}/application_stopped"
status_app() {
    [ -r "$APP_PID" ] || return 1
    app_pid=$(cat "$APP_PID")
    case "$app_pid" in ''|*[!0-9]*) return 1 ;; esac
    [ "$app_pid" -gt 1 ] || return 1
    kill -0 "$app_pid" 2>/dev/null || return 1
    [ -r "/proc/${app_pid}/cmdline" ] || return 1
    tr '\000' '\n' < "/proc/${app_pid}/cmdline" | grep -Fx "$SELF" >/dev/null || return 1
    tr '\000' '\n' < "/proc/${app_pid}/cmdline" | grep -Fx supervisor >/dev/null
}
case "${1:-}" in
    start)
        status_app && exit 0
        rm -f "$APP_STOP"
        # Detached children close the supervisor lock descriptor.
        nohup /bin/sh "$SELF" supervisor </dev/null >/dev/null 2>&1 &
        attempt=0
        while [ "$attempt" -lt 10 ]; do
            status_app && exit 0
            sleep 1
            attempt=$((attempt + 1))
        done
        exit 1
        ;;
    supervisor)
        exec 9>"$APP_LOCK"
        flock -n 9 || exit 0
        echo "$$" > "$APP_PID"
        trap 'touch "$APP_STOP"; /bin/sh "$SCRIPT_PATH" stop 9>&- >/dev/null 2>&1; rm -f "$APP_PID"; exit 0' TERM INT HUP
        # Initialize auto-start markers before the maintenance loop can run.
        /bin/sh "$SCRIPT_PATH" start 9>&- >/dev/null 2>&1
        while [ ! -f "$APP_STOP" ]; do
            /bin/sh "$SCRIPT_PATH" ensure 9>&- >/dev/null 2>&1
            # Bounded log storage, independent of connection state.
            for app_log in "${VAR_DIR}/npc.log"; do
                [ -f "$app_log" ] || continue
                app_log_size=$(wc -c < "$app_log")
                if [ "$app_log_size" -gt 2097152 ]; then
                    mv -f "$app_log" "${app_log}.1"
                fi
            done
            sleep 10 &
            wait $!
        done
        rm -f "$APP_PID"
        ;;
    stop)
        touch "$APP_STOP"
        /bin/sh "$SCRIPT_PATH" stop >/dev/null 2>&1
        if status_app; then
            kill -TERM "$app_pid" 2>/dev/null || true
            attempt=0
            while status_app && [ "$attempt" -lt 15 ]; do
                sleep 1
                attempt=$((attempt + 1))
            done
            if status_app; then kill -KILL "$app_pid" 2>/dev/null || true; fi
        fi
        rm -f "$APP_PID"
        ;;
    status)
        status_app && exit 0
        exit 3
        ;;
    *) exit 1 ;;
esac
