#!/bin/bash

set -uo pipefail

# ==============================================================================
# CONFIGURATION
# ==============================================================================
TARGET_USER="andrew"
USER_HOME="/home/$TARGET_USER"
MONITOR_SCRIPT="$USER_HOME/monitor_manager.sh"
KIOSK_SCRIPT="$USER_HOME/kiosk_session.sh"


MIN_SCRIPT_SIZE=2048 # Minimum size for a generated script in bytes.

# Marker that startauto.sh/overlay can read to know this update did not finish.
FAIL_FLAG="$USER_HOME/UPDATE_FAILED"

# leave the existing scripts untouched, drop a failure marker, and remove any partial temp output
fail_update() {
    echo "UPDATE ERROR: $1" >&2
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" > "$FAIL_FLAG"
    rm -f "$MONITOR_SCRIPT.tmp" "$KIOSK_SCRIPT.tmp"
    exit 1
}

# Validate a freshly-generated "$dest.tmp", then atomically install it over the
# live file. Only swaps in the new file when it is large enough AND parses
# cleanly, so a corrupt/truncated generation can never replace a working script.
install_script() {
    local dest="$1"
    local tmp="$dest.tmp"
    local size
    [ -f "$tmp" ] || fail_update "generation produced no file: $tmp"
    size=$(stat -c%s "$tmp" 2>/dev/null || echo 0)
    [ "$size" -ge "$MIN_SCRIPT_SIZE" ] || fail_update "generated $tmp too small ($size bytes)"
    bash -n "$tmp" || fail_update "generated $tmp failed syntax check"
    chmod +x "$tmp" || fail_update "could not chmod $tmp"
    chown "$TARGET_USER:$TARGET_USER" "$tmp" || fail_update "could not chown $tmp"
    mv -f "$tmp" "$dest" || fail_update "could not install $dest"
    echo " Installed $dest ($size bytes)"
}

# A previous failed run may have left a stale marker; clear it before starting.
rm -f "$FAIL_FLAG"

# ==============================================================================
# 2. GENERATE MONITOR MANAGER
# ==============================================================================
echo " Generating $MONITOR_SCRIPT..."

# We use 'EOF' (quoted) to prevent variables inside from expanding during generation
cat << 'EOF' > "$MONITOR_SCRIPT.tmp"
#!/bin/bash

SYS_PORT_A="HDMI3"
SYS_PORT_B="HDMI4"

PORT_A="HDMI-0"
PORT_B="HDMI-1"
FLAG_FILE="/tmp/dual_monitor_active" # <--- The communication signal


get_status() {
    #cat /sys/class/extcon/extcon0/state | grep "^$1" | grep "1"
    xrandr | grep "^$1" | grep -w "connected"
}


LAST_STATE="none"

# --- CRITICAL ENVIRONMENT SETUP ---
# 1. Force the script to talk to the first X Display
export DISPLAY=:0

# 3. Add path to ensure we find the xrandr binary
export PATH=/usr/bin:/bin:/usr/local/bin:$PATH

# 0. Wait for X11 to accept connections
# We loop until xrandr returns success (exit code 0)
echo "Waiting for X Server..."
until xrandr >/dev/null 2>&1; do
    sleep 1
done
echo "X Server is ready."

while true; do
    if get_status "$PORT_A" > /dev/null; then STAT_A=1; else STAT_A=0; fi
    if get_status "$PORT_B" > /dev/null; then STAT_B=1; else STAT_B=0; fi
    CURRENT_STATE="${STAT_A}${STAT_B}"
    #echo $(xrandr)

    if [ "$CURRENT_STATE" != "$LAST_STATE" ]; then
        echo "Got a state change $LAST_STATE -> $CURRENT_STATE"
        
        case $CURRENT_STATE in
            "11") 
                # DUAL MODE
                xrandr --output $PORT_A --mode "1920x1080" --pos 0x0 --primary \
                       --output $PORT_B --mode "1920x1080" --pos 0x0
                
                # Wait for X11 to settle so the coordinate space exists
                sleep 1 
                
                # Signal the app!
                touch $FLAG_FILE
                ;;
            *)
                # SINGLE MODE (Handle A or B specific switching logic here as before)
                if [ "$CURRENT_STATE" == "10" ]; then
                     xrandr --output $PORT_A --mode "1920x1080" --pos 0x0 --primary --output $PORT_B --off
                elif [ "$CURRENT_STATE" == "01" ]; then
                     xrandr --output $PORT_B --mode "1920x1080" --pos 0x0 --primary --output $PORT_A --off
                fi

                # Remove the signal file
                rm -f $FLAG_FILE
                ;;
        esac
        
        LAST_STATE="$CURRENT_STATE"
    fi
    sleep 2
done
EOF

# Validate the generated temp file, then atomically install it.
install_script "$MONITOR_SCRIPT"

# ==============================================================================
# 3. GENERATE KIOSK SESSION
# ==============================================================================
echo " Generating $KIOSK_SCRIPT..."

cat << 'EOF' > "$KIOSK_SCRIPT.tmp"
#!/bin/bash
KIOSKVERSION="1.1.0"
# ==============================================================================
# LOGGING CONFIGURATION
# ==============================================================================
LOG_DIR="/home/andrew/logs"
MAX_LOGS=20  # Keep the newest 20 days of logs
MAX_SIZE_BYTES=20971520 # 20MB (20 * 1024 * 1024)

# 1. Ensure Directory Exists
mkdir -p "$LOG_DIR"

# 2. Define the Log File for TODAY
# Using only the date ensures all crashes/restarts today go into one file.
TODAY=$(date +%Y-%m-%d)
CURRENT_LOG="$LOG_DIR/overlay_$TODAY.log"
KIOSK_LOG="$LOG_DIR/kiosk_$TODAY.log"

# 3. SANITY CHECK: File Size
# If the log file exists and is bigger than 50MB, rename it so we start fresh.
if [ -f "$CURRENT_LOG" ]; then
    FILE_SIZE=$(stat -c%s "$CURRENT_LOG")
    if [ $FILE_SIZE -ge $MAX_SIZE_BYTES ]; then
        echo "Log file $CURRENT_LOG is too large $FILE_SIZE bytes. Rotating..."
        
        # Rename it with a timestamp so it isn't overwritten, but is no longer the "active" log
        # Example: overlay_2023-10-27.log -> overlay_2023-10-27_14-30-00.rotated.log
        TIMESTAMP=$(date +%H-%M-%S)
        mv "$CURRENT_LOG" "${CURRENT_LOG%.log}_${TIMESTAMP}.rotated.log"
    fi
fi

# 4. CLEANUP: Keep only the newest N logs
# We use a subshell to safely change directory for the cleanup logic
(
    cd "$LOG_DIR"
    # ls -tp: List files sorted by time (newest first), add / to directory names
    # grep -v '/$': Remove directories from the list (only keep files)
    # tail -n +$((MAX_LOGS + 1)): Skip the first N files, output the rest (the old ones)
    # xargs -I {} rm -- "{}": Delete the old files found
    ls -tp overlay_*.log 2>/dev/null | grep -v '/$' | tail -n +$((MAX_LOGS + 1)) | xargs -I {} rm -- "{}"
    ls -tp kiosk_*.log 2>/dev/null | grep -v '/$' | tail -n +$((MAX_LOGS + 1)) | xargs -I {} rm -- "{}"
)



# 5. Add a "Session Break" Marker
# Since we are appending, this helps you see where a new session began in the file.
echo "" >> "$CURRENT_LOG"
echo "======================================================================" >> "$CURRENT_LOG"
echo " RAYLIB START: $(date '+%Y-%m-%d %H:%M:%S')" >> "$CURRENT_LOG"
echo "======================================================================" >> "$CURRENT_LOG"

echo "" >> "$KIOSK_LOG"
echo "======================================================================" >> "$KIOSK_LOG"
echo " KIOSK SESSION START: $(date '+%Y-%m-%d %H:%M:%S')" >> "$KIOSK_LOG"
echo "======================================================================" >> "$KIOSK_LOG"


# 0. PRE-FLIGHT CLEANUP
pkill -f "monitor_manager.sh"

# Double check: wait a split second to ensure processes are dead
sleep .5

# 1. Setup
xset s off -dpms
xhost +local:root

# 2. Start Monitor Manager
/home/andrew/monitor_manager.sh >> "$KIOSK_LOG" 2>&1 &

MANAGER_PID=$!

# 3. Start Window Manager
export DISPLAY=:0


mkdir -p /home/andrew/.config/autostart
echo -e "[Desktop Entry]\nHidden=true" > /home/andrew/.config/autostart/clipit-startup.desktop
chown -R andrew:andrew /home/andrew/.config/autostart

# Target files that cause networking and system popups
TARGETS=(
  "/etc/xdg/autostart/nm-applet.desktop"
  "/etc/xdg/autostart/blueman.desktop"
  "/etc/xdg/autostart/update-notifier.desktop"
)

for FILE in "${TARGETS[@]}"; do
  if [ -f "$FILE" ]; then
    # Only append Hidden=true if it isn't already present
    if ! grep -q "Hidden=true" "$FILE"; then
      sudo sed -i '/^\[Desktop Entry\]/a Hidden=true' "$FILE"
    fi
  fi
done

# Kill any notification processes that managed to start before this script
sudo pkill -9 nm-applet
sudo pkill -9 notify-osd
sudo pkill -9 dunst
sudo pkill -9 update-notifier

# Optional: Ensure settings are applied to the root user's environment
sudo gsettings set org.gnome.nm-applet disable-connected-notifications tru

openbox-session &

# 4. Wait for X11
sleep 1


# Target files that cause networking and system popups
TARGETS=(
  "/etc/xdg/autostart/nm-applet.desktop"
  "/etc/xdg/autostart/blueman.desktop"
  "/etc/xdg/autostart/update-notifier.desktop"
)

for FILE in "${TARGETS[@]}"; do
  if [ -f "$FILE" ]; then
    # Only append Hidden=true if it isn't already present
    if ! grep -q "Hidden=true" "$FILE"; then
      sudo sed -i '/^\[Desktop Entry\]/a Hidden=true' "$FILE"
    fi
  fi
done

# Kill any notification processes that managed to start before this script
sudo pkill -9 nm-applet
sudo pkill -9 notify-osd
sudo pkill -9 dunst
sudo pkill -9 update-notifier

# Optional: Ensure settings are applied to the root user's environment
sudo gsettings set org.gnome.nm-applet disable-connected-notifications tru

# 5. Run the Overlay
cd /home/andrew/Desktop/ShareContext

sudo DISPLAY=:0 \
     HOME=/home/andrew \
     STARTVERSION="${1:-2.0.0}" \
     KIOSKVERSION=$KIOSKVERSION \
     CONFIGURATION=RELEASE \
     ./overlay "$@" 2>&1 | gawk '!/Home directory not accessible/ { date=strftime("%Y-%m-%d %H:%M:%S"); print date,"[overlay]",$0; fflush() }' >> "$CURRENT_LOG"

# ---------------------------------------------------------
# 6. CLEANUP
# ---------------------------------------------------------

echo "Raylib app exited. Cleaning up monitor manager..."

if ps -p $MANAGER_PID > /dev/null; then
    kill $MANAGER_PID
fi

exit 0
EOF

# Validate the generated temp file, then atomically install it.
install_script "$KIOSK_SCRIPT"

# ==============================================================================
# 5. CREATE LOG DIRECTORY
# ==============================================================================
mkdir -p "$USER_HOME/logs"
chown -R $TARGET_USER:$TARGET_USER "$USER_HOME/logs"

# ==============================================================================
# 6. FINAL SELF-TEST
# ==============================================================================
# Confirm both live scripts ended up valid before declaring success. install_script
# already validated each, but re-check the installed files in case anything below
# them touched the targets. If either is bad, signal failure rather than reboot
# into a broken kiosk.
for SCRIPT in "$MONITOR_SCRIPT" "$KIOSK_SCRIPT"; do
    [ -f "$SCRIPT" ] || fail_update "missing after install: $SCRIPT"
    SIZE=$(stat -c%s "$SCRIPT" 2>/dev/null || echo 0)
    [ "$SIZE" -ge "$MIN_SCRIPT_SIZE" ] || fail_update "installed $SCRIPT too small ($SIZE bytes)"
    bash -n "$SCRIPT" || fail_update "installed $SCRIPT failed syntax check"
done

pkill xinit
sleep 1
killall Xorg
sleep 2

echo " Update Complete. Reboot needed to apply changes."
