#!/bin/bash

# Kivy Signage Player Startup Script with Watchdog
# This script monitors and auto-restarts the player if it crashes

# Get the directory where this script is located
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Configuration
MAX_RETRIES=999999  # Effectively unlimited retries
RESTART_DELAY=5     # Seconds to wait before restart
HEALTH_CHECK_INTERVAL=30  # Seconds between health checks
HEARTBEAT_FILE="$SCRIPT_DIR/.player_heartbeat"
STOP_FLAG_FILE="$SCRIPT_DIR/.player_stop_requested"
LOG_FILE="$SCRIPT_DIR/player_watchdog.log"

# Ensure log file is writable
if [ ! -w "$(dirname "$LOG_FILE")" ]; then
    LOG_FILE="/tmp/kivy-player-watchdog.log"
fi

# Function to log messages (MUST be defined before use)
log_message() {
    local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $1"
    echo "$msg"
    # Try to write to log file, ignore errors if permission denied
    echo "$msg" >> "$LOG_FILE" 2>/dev/null || true
}

# Load user's environment from systemd user session (most reliable method)
# This ensures we get the proper DISPLAY/WAYLAND_DISPLAY and session variables
load_user_environment() {
    # Try to get environment from active user session via systemctl
    local user_env
    if command -v systemctl &>/dev/null; then
        user_env=$(systemctl --user show-environment 2>/dev/null)
        if [ -n "$user_env" ]; then
            # Extract display-related variables without subshell to preserve exports
            while IFS='=' read -r key value; do
                case "$key" in
                    DISPLAY|WAYLAND_DISPLAY|XDG_RUNTIME_DIR|DBUS_SESSION_BUS_ADDRESS)
                        export "$key=$value"
                        ;;
                esac
            done <<< "$user_env"
            
            log_message "Loaded user environment from systemctl --user"
            
            # Verify we got valid display
            if [ -n "$DISPLAY" ] || [ -n "$WAYLAND_DISPLAY" ]; then
                log_message "Display environment ready: DISPLAY='$DISPLAY' WAYLAND_DISPLAY='$WAYLAND_DISPLAY'"
                return 0
            else
                log_message "Systemctl didn't provide display variables, trying fallback..."
            fi
        fi
    fi
    
    # Fallback: detect display manually
    log_message "Falling back to manual display detection..."
    
    if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
        # Try to detect Wayland display
        if [ -S "/run/user/$(id -u)/wayland-0" ]; then
            export WAYLAND_DISPLAY=wayland-0
            log_message "Detected Wayland display: $WAYLAND_DISPLAY"
        # Try to detect X11 display
        elif [ -S "/tmp/.X11-unix/X0" ]; then
            export DISPLAY=:0
            log_message "Detected X11 display: $DISPLAY"
        else
            # Wait for display to come up (useful for systemd or delayed starts)
            log_message "Waiting for display server to be ready (up to 30 seconds)..."
            for i in {1..30}; do
                sleep 1
                if [ -S "/run/user/$(id -u)/wayland-0" ] 2>/dev/null; then
                    export WAYLAND_DISPLAY=wayland-0
                    log_message "Display server detected on attempt $i: Wayland"
                    return 0
                elif [ -S "/tmp/.X11-unix/X0" ] 2>/dev/null; then
                    export DISPLAY=:0
                    log_message "Display server detected on attempt $i: X11"
                    return 0
                fi
            done
        fi
    fi
    
    # Verify we have a display now
    if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
        log_message "WARNING: No display server detected. This may cause graphics issues."
        return 1
    fi
    
    log_message "Display environment ready: DISPLAY=$DISPLAY WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
    return 0
}

# Load the user environment early
load_user_environment

# Function to configure display output to Full HD (1920x1080)
configure_display_resolution() {
    log_message "🖥️  Configuring display output to Full HD (1920x1080)..."
    
    # Method 1: Try xrandr (works on X11 systems)
    if command -v xrandr &>/dev/null && [ -n "$DISPLAY" ]; then
        log_message "Attempting to set resolution via xrandr..."
        
        # Get the primary display
        primary_display=$(xrandr --query 2>/dev/null | grep " connected" | grep "primary\|preferred" | head -n 1 | awk '{print $1}')
        
        if [ -z "$primary_display" ]; then
            primary_display=$(xrandr --query 2>/dev/null | grep " connected" | head -n 1 | awk '{print $1}')
        fi
        
        if [ -n "$primary_display" ]; then
            # Set output to 1920x1080 @ 60Hz
            xrandr --output "$primary_display" --mode 1920x1080 --rate 60 2>/dev/null
            if [ $? -eq 0 ]; then
                log_message "✓ Display resolution set to 1920x1080 via xrandr"
                return 0
            fi
        fi
    fi
    
    # Method 2: Try tvservice (native Raspberry Pi tool)
    if command -v tvservice &>/dev/null; then
        log_message "Attempting to set resolution via tvservice (RPi native)..."
        
        # Get current HDMI status
        hdmi_mode=$(tvservice -s 2>/dev/null | grep -oP 'DMT mode \K\d+')
        
        # Set to HDMI mode 16 (1920x1080 @ 60Hz) - standard Full HD
        tvservice -e "DMT 16" 2>/dev/null
        if [ $? -eq 0 ]; then
            log_message "✓ Display resolution set to 1920x1080 via tvservice (DMT mode 16)"
            return 0
        fi
    fi
    
    # Method 3: Configure via /boot/config.txt (persistent RPi config)
    if [ -f "/boot/config.txt" ] && command -v sudo &>/dev/null; then
        log_message "Checking /boot/config.txt for display settings..."
        
        # These settings ensure Full HD output on large displays
        if ! grep -q "hdmi_group=2" /boot/config.txt; then
            log_message "Adding HDMI display configuration to /boot/config.txt..."
            # Backup config first
            sudo cp /boot/config.txt /boot/config.txt.backup.$(date +%s)
            
            # Add Full HD configuration
            echo "" | sudo tee -a /boot/config.txt > /dev/null
            echo "# Kiwy Signage Player - Full HD Display Configuration" | sudo tee -a /boot/config.txt > /dev/null
            echo "hdmi_group=2" | sudo tee -a /boot/config.txt > /dev/null        # DMT (monitor timings)
            echo "hdmi_mode=16" | sudo tee -a /boot/config.txt > /dev/null        # 1920x1080 @ 60Hz
            echo "hdmi_drive=2" | sudo tee -a /boot/config.txt > /dev/null        # Normal HDMI mode
            echo "disable_overscan=1" | sudo tee -a /boot/config.txt > /dev/null  # Disable overscan
            echo "framebuffer_width=1920" | sudo tee -a /boot/config.txt > /dev/null
            echo "framebuffer_height=1080" | sudo tee -a /boot/config.txt > /dev/null
            
            log_message "✓ HDMI configuration added to /boot/config.txt"
            log_message "⚠️  Display settings require reboot to take effect"
            return 0
        else
            log_message "✓ /boot/config.txt already configured for Full HD"
        fi
    fi
    
    log_message "Display configuration completed (1920x1080 Full HD target)"
}

# Configure display before starting player
configure_display_resolution

# Function to check if player is healthy
check_health() {
    # Check if heartbeat file exists and is recent (within last 60 seconds)
    if [ -f "$HEARTBEAT_FILE" ]; then
        local last_update=$(stat -c %Y "$HEARTBEAT_FILE" 2>/dev/null || echo 0)
        local current_time=$(date +%s)
        local diff=$((current_time - last_update))
        
        if [ $diff -lt 60 ]; then
            return 0  # Healthy
        else
            log_message "⚠️  Player heartbeat stale (${diff}s old)"
            return 1  # Unhealthy
        fi
    else
        # If heartbeat file doesn't exist yet, assume player is starting
        return 0
    fi
}

# Cleanup function
cleanup() {
    log_message "🛑 Watchdog received stop signal"
    rm -f "$HEARTBEAT_FILE"
    rm -f "$STOP_FLAG_FILE"
    exit 0
}

# Trap signals for graceful shutdown
trap cleanup SIGINT SIGTERM

log_message "=========================================="
log_message "🚀 Kivy Signage Player Watchdog Started"
log_message "=========================================="
log_message "Project directory: $SCRIPT_DIR"
log_message "Max retries: Unlimited"
log_message "Restart delay: ${RESTART_DELAY}s"
log_message ""

# Remove old stop flag if exists (fresh start)
rm -f "$STOP_FLAG_FILE"

# Change to the project directory
cd "$SCRIPT_DIR"

# Check if configuration exists
if [ ! -f "config/app_config.json" ]; then
    log_message "⚠️  WARNING: Configuration file not found!"
    log_message "Player may not function correctly without configuration"
fi

# Main watchdog loop
retry_count=0
while true; do
    retry_count=$((retry_count + 1))
    
    log_message ""
    log_message "=========================================="
    log_message "▶️  Starting player (attempt #${retry_count})"
    log_message "=========================================="
    
    # Clean old heartbeat
    rm -f "$HEARTBEAT_FILE"
    
    # Activate virtual environment if it exists
    if [ -f "$SCRIPT_DIR/.venv/bin/activate" ]; then
        source "$SCRIPT_DIR/.venv/bin/activate"
    fi
    
    # Start the player
    cd "$SCRIPT_DIR/src"
    python3 main.py &
    PLAYER_PID=$!
    
    log_message "Player PID: $PLAYER_PID"
    
    # Monitor the player
    while true; do
        sleep $HEALTH_CHECK_INTERVAL
        
        # Check if process is still running
        if ! kill -0 $PLAYER_PID 2>/dev/null; then
            log_message "❌ Player process crashed or stopped (PID: $PLAYER_PID)"
            break
        fi
        
        # Check health via heartbeat
        if ! check_health; then
            log_message "❌ Player health check failed - may be frozen"
            kill $PLAYER_PID 2>/dev/null
            sleep 2
            kill -9 $PLAYER_PID 2>/dev/null
            break
        fi
        
        # Player is healthy, continue monitoring
    done
    
    # Player stopped or crashed
    # Check if user requested intentional exit
    if [ -f "$STOP_FLAG_FILE" ]; then
        log_message "✋ Stop flag detected - user requested exit via password"
        log_message "Watchdog will NOT restart the player"
        log_message "To restart, run ./start.sh again"
        rm -f "$HEARTBEAT_FILE"
        break
    fi
    
    log_message "⏳ Waiting ${RESTART_DELAY}s before restart..."
    sleep $RESTART_DELAY
    
    # Ensure old player process is gone before restarting
    kill -9 $PLAYER_PID 2>/dev/null
    
done

log_message ""
log_message "=========================================="
log_message "Watchdog stopped"
log_message "=========================================="
