#!/bin/bash
#
# wssshc        Startup script for WebSocket SSH Client
#
# chkconfig: 345 84 16
# description: WebSocket SSH Client - Registers with wssshd server and handles SSH connections
# processname: wssshc
# pidfile: /var/run/wssshc.pid
# config: /etc/wssshc.conf

### BEGIN INIT INFO
# Provides: wssshc
# Required-Start: $local_fs $network $syslog
# Required-Stop: $local_fs $network $syslog
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: WebSocket SSH Client
# Description: WebSocket SSH Client registers with wssshd server and handles SSH connections
### END INIT INFO

# Source function library (Debian/Ubuntu)
. /lib/lsb/init-functions

# Configuration
NAME="wssshc"
DAEMON="/usr/bin/wssshc"
WATCHDOG="/usr/sbin/wssshc-watchdog"
PIDFILE="/var/run/wssshc.pid"
WATCHDOG_PIDFILE="/var/run/wssshc-watchdog.pid"
DEFAULT_FILE="/etc/default/wssshc"
CONFIG_SYSTEM="/etc/wssshc.conf"
CONFIG_USER="$HOME/.config/wsssh/wssshc.conf"
LOG_FACILITY="daemon"
USER="wssshc"
GROUP="wssshc"

# Check if we're running as root
if [ $(id -u) != 0 ]; then
    echo "Error: This script must be run as root"
    exit 1
fi

# Function to check if START is enabled in /etc/default/wssshc
check_start_enabled() {
    if [ ! -f "$DEFAULT_FILE" ]; then
        echo "Configuration file $DEFAULT_FILE not found"
        return 1
    fi

    # Read the START variable
    START_VALUE=$(grep -E "^START=" "$DEFAULT_FILE" | cut -d'=' -f2 | tr -d '[:space:]')

    if [ -z "$START_VALUE" ]; then
        echo "START variable not found in $DEFAULT_FILE"
        return 1
    fi

    # Check if START is set to a positive value
    case "$START_VALUE" in
        [Yy]|[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1)
            return 0
            ;;
        *)
            echo "START is set to '$START_VALUE', service will not start"
            return 1
            ;;
    esac
}

# Function to find configuration file
find_config_file() {
    # Check system config first
    if [ -f "$CONFIG_SYSTEM" ]; then
        echo "$CONFIG_SYSTEM"
        return 0
    fi

    # Check user config (run as wsssh user to get correct HOME)
    if su - "$USER" -c "[ -f '$CONFIG_USER' ]" 2>/dev/null; then
        echo "$CONFIG_USER"
        return 0
    fi

    echo "No configuration file found"
    return 1
}

# Function to check if process is running
is_running() {
    if [ -f "$PIDFILE" ]; then
        local pid=$(cat "$PIDFILE")
        if [ -d "/proc/$pid" ]; then
            return 0
        else
            # Stale PID file
            rm -f "$PIDFILE"
            return 1
        fi
    fi
    return 1
}

# Function to start the daemon
start() {
    echo -n "Starting $NAME: "

    # Check if daemon is already running
    if is_running; then
        local pid=$(cat "$PIDFILE")
        echo "already running (PID: $pid)"
        return 0
    fi

    # Check if START is enabled
    if ! check_start_enabled; then
        echo "disabled in $DEFAULT_FILE"
        echo "To enable $NAME, set START=Y in $DEFAULT_FILE"
        return 1
    fi

    # Find configuration file
    CONFIG_FILE=$(find_config_file)
    if [ $? -ne 0 ]; then
        echo "configuration file not found"
        echo "Please create a configuration file:"
        echo "  System-wide: $CONFIG_SYSTEM"
        echo "  User-specific: $CONFIG_USER"
        echo "You can use the example configuration as a template:"
        echo "  cp /usr/share/wsssh/wssshc.conf.example $CONFIG_SYSTEM"
        return 1
    fi

    # Check if daemon executable exists
    if [ ! -x "$DAEMON" ]; then
        echo "daemon executable $DAEMON not found or not executable"
        return 1
    fi

    # Create necessary directories
    mkdir -p /var/run /var/log/wssshc
    chown $USER:$GROUP /var/run /var/log/wssshc 2>/dev/null || true

    # Start the daemon directly
    echo "Starting daemon..."
    if "$DAEMON" >> /var/log/wssshc/wssshc.log 2>&1 &
    then
        echo $! > "$PIDFILE"
        echo "Daemon started successfully"
    else
        echo "FAILED"
        echo "Could not start daemon"
        return 1
    fi

    # Wait for daemon to be fully running
    local count=0
    while [ $count -lt 10 ] && ! is_running; do
        echo "Waiting for daemon to start... ($count/10)"
        sleep 1
        count=$((count + 1))
    done

    if is_running; then
        local pid=$(cat "$PIDFILE")
        echo "Daemon is running (PID: $pid)"

        # Stop any existing watchdog before starting a new one
        if [ -f "$WATCHDOG_PIDFILE" ] || pgrep -f "wssshc-watchdog" >/dev/null 2>&1; then
            echo "Stopping existing watchdog..."
            $WATCHDOG stop >/dev/null 2>&1
            sleep 2
        fi

        # Now start the watchdog to monitor the running daemon
        echo "Starting watchdog..."
        if [ -x "$WATCHDOG" ]; then
            $WATCHDOG start >/dev/null 2>&1

            # Wait for watchdog PID file to be created (max 5 seconds)
            local count=0
            while [ $count -lt 10 ] && [ ! -f "$WATCHDOG_PIDFILE" ]; do
                sleep 0.5
                count=$((count + 1))
            done

            if [ -f "$WATCHDOG_PIDFILE" ]; then
                watchdog_pid=$(cat "$WATCHDOG_PIDFILE" 2>/dev/null)
                if [ -n "$watchdog_pid" ] && kill -0 "$watchdog_pid" 2>/dev/null; then
                    echo "OK"
                    return 0
                else
                    echo "OK (daemon running, watchdog process not responding)"
                    return 0
                fi
            else
                echo "OK (daemon running, watchdog PID file not found)"
                return 0
            fi
        else
            echo "OK (daemon running, no watchdog available)"
            return 0
        fi
    else
        echo "FAILED"
        echo "Daemon failed to start properly"
        return 1
    fi
}

# Function to stop the daemon
stop() {
    echo -n "Stopping $NAME: "

    # First, try to stop the watchdog if it's running
    if [ -f "$WATCHDOG_PIDFILE" ]; then
        echo "Stopping watchdog..."
        $WATCHDOG stop >/dev/null 2>&1
        sleep 2
    fi

    # Check if daemon is running via PID file
    if is_running; then
        echo "Stopping daemon via PID file..."
        local pid=$(cat "$PIDFILE")
        # Try to stop gracefully first
        kill -TERM "$pid" 2>/dev/null
        sleep 2

        # Check if it's still running
        if kill -0 "$pid" 2>/dev/null; then
            # Force kill if still running
            kill -KILL "$pid" 2>/dev/null
            sleep 1
        fi
    fi

    # Also kill any wssshc processes that might be running (regardless of PID file)
    echo "Ensuring all wssshc processes are stopped..."
    pkill -TERM -f "^/usr/bin/wssshc" 2>/dev/null || true
    sleep 2
    pkill -KILL -f "^/usr/bin/wssshc" 2>/dev/null || true

    # Clean up PID files
    rm -f "$PIDFILE" "$WATCHDOG_PIDFILE"

    # Final check
    if is_running; then
        echo "FAILED"
        return 1
    else
        echo "OK"
        return 0
    fi
}

# Function to restart the daemon
restart() {
    stop
    sleep 2
    start
}

# Function to check status
status() {
    # Check watchdog status
    if [ -f "$WATCHDOG_PIDFILE" ]; then
        local watchdog_pid=$(cat "$WATCHDOG_PIDFILE")
        if kill -0 "$watchdog_pid" 2>/dev/null; then
            echo "Watchdog is running (PID: $watchdog_pid)"
        else
            echo "Watchdog PID file exists but process is not running"
            rm -f "$WATCHDOG_PIDFILE"
        fi
    else
        echo "Watchdog is not running"
    fi

    # Check daemon status
    if is_running; then
        local pid=$(cat "$PIDFILE")
        echo "$NAME daemon is running (PID: $pid)"
        return 0
    else
        echo "$NAME daemon is not running"
        return 3
    fi
}

# Function to reload configuration
reload() {
    echo -n "Reloading $NAME configuration: "

    if ! is_running; then
        echo "not running"
        return 1
    fi

    local pid=$(cat "$PIDFILE")
    kill -HUP $pid 2>/dev/null

    if [ $? -eq 0 ]; then
        echo "OK"
        return 0
    else
        echo "FAILED"
        return 1
    fi
}

# Main script logic
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    reload)
        reload
        ;;
    status)
        status
        ;;
    condrestart|try-restart)
        if is_running; then
            restart
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|reload|status|condrestart}"
        exit 2
        ;;
esac

exit $?