#!/bin/bash
#
# Nuke Network Namespace Isolation Launcher
# Launches Nuke in a network namespace with only localhost access
# This blocks ALL external network connections while preserving frameserver communication
#
# Usage:
#   sudo bash nuke_isolated.sh [NUKE_ARGS]  # Launch Nuke in isolated namespace
#   sudo bash nuke_isolated.sh --nukex      # Launch NukeX in isolated namespace
#   sudo bash nuke_isolated.sh --cleanup    # Clean up namespace (run if Nuke crashes)
#   sudo bash nuke_isolated.sh --status     # Check namespace status
#

set -e

# Configuration
NUKE_EXECUTABLE="/home/nicholai/Nuke15.2v6/Nuke15.2"
NUKE_ALT_EXECUTABLE="/home/nicholai/Nuke15.2v6/Nuke"  # Fallback name
NAMESPACE="nuke_isolated"
ACTUAL_USER="${SUDO_USER:-$USER}"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log() {
    echo -e "$1"
}

check_root() {
    if [ "$EUID" -ne 0 ]; then
        log "${RED}Error: This script must be run as root${NC}"
        log "Usage: sudo bash $0"
        exit 1
    fi
}

check_nuke_exists() {
    if [ -f "$NUKE_EXECUTABLE" ]; then
        log "${GREEN}Found Nuke executable: $NUKE_EXECUTABLE${NC}"
        return 0
    elif [ -f "$NUKE_ALT_EXECUTABLE" ]; then
        log "${YELLOW}Using alternate executable: $NUKE_ALT_EXECUTABLE${NC}"
        NUKE_EXECUTABLE="$NUKE_ALT_EXECUTABLE"
        return 0
    else
        log "${RED}Error: Nuke executable not found${NC}"
        log "Expected locations:"
        log "  $NUKE_EXECUTABLE"
        log "  $NUKE_ALT_EXECUTABLE"
        log ""
        log "Update NUKE_EXECUTABLE in this script to match your installation"
        exit 1
    fi
}

namespace_exists() {
    ip netns list 2>/dev/null | grep -q "^$NAMESPACE\$"
}

create_namespace() {
    log "${BLUE}Creating network namespace: $NAMESPACE${NC}"

    if namespace_exists; then
        log "${YELLOW}Namespace already exists, cleaning up first...${NC}"
        cleanup_namespace
    fi

    # Create namespace
    ip netns add "$NAMESPACE"
    log "Created namespace: $NAMESPACE"

    # Bring up loopback interface (allows 127.0.0.1 connections)
    ip netns exec "$NAMESPACE" ip link set lo up
    log "Enabled loopback interface (frameserver will work)"

    # Verify namespace configuration
    log ""
    log "${GREEN}Namespace configuration:${NC}"
    ip netns exec "$NAMESPACE" ip addr show lo | grep -E "lo:|inet "
}

cleanup_namespace() {
    log "${YELLOW}Cleaning up namespace: $NAMESPACE${NC}"

    if namespace_exists; then
        # Kill any processes still in the namespace
        ip netns pids "$NAMESPACE" 2>/dev/null | while read pid; do
            log "Killing process $pid in namespace"
            kill -9 "$pid" 2>/dev/null || true
        done

        # Delete namespace
        ip netns delete "$NAMESPACE"
        log "Deleted namespace: $NAMESPACE"
    else
        log "Namespace does not exist, nothing to clean up"
    fi
}

show_status() {
    log "${GREEN}=== Network Namespace Status ===${NC}"
    echo ""

    if namespace_exists; then
        log "${GREEN}Namespace '$NAMESPACE' exists${NC}"
        echo ""

        log "Network interfaces in namespace:"
        ip netns exec "$NAMESPACE" ip addr show

        echo ""
        log "Processes running in namespace:"
        if ip netns pids "$NAMESPACE" 2>/dev/null | grep -q .; then
            ip netns pids "$NAMESPACE" | while read pid; do
                ps -p "$pid" -o pid,cmd --no-headers
            done
        else
            log "  No processes running"
        fi
    else
        log "${YELLOW}Namespace '$NAMESPACE' does not exist${NC}"
    fi
}

launch_nuke() {
    log "${GREEN}=== Launching Nuke in Isolated Network Namespace ===${NC}"
    log ""
    log "Configuration:"
    log "  Executable: $NUKE_EXECUTABLE"
    log "  Namespace: $NAMESPACE"
    log "  User: $ACTUAL_USER"
    log "  Network access: LOCALHOST ONLY (127.0.0.1)"
    log ""
    log "${YELLOW}WARNING: All external network features will be disabled${NC}"
    log "  - No telemetry transmission"
    log "  - No online help"
    log "  - No license server access (if using floating licenses)"
    log "  + Frameserver will work (uses localhost)"
    log ""

    read -p "Continue? (y/n): " confirm
    if [ "$confirm" != "y" ]; then
        log "Aborted"
        exit 0
    fi

    # Create namespace
    create_namespace

    log ""
    log "${BLUE}Launching Nuke...${NC}"
    log ""

    # Store user's display and X auth for GUI
    XAUTHORITY_PATH="${XAUTHORITY:-/home/$ACTUAL_USER/.Xauthority}"
    DISPLAY_VALUE="${DISPLAY:-:1}"

    # Capture Wayland/Hyprland environment variables to prevent cursor scaling issues
    WAYLAND_DISPLAY_VALUE="${WAYLAND_DISPLAY:-}"
    XDG_RUNTIME_DIR_VALUE="${XDG_RUNTIME_DIR:-/run/user/1000}"
    XCURSOR_SIZE_VALUE="${XCURSOR_SIZE:-24}"
    XCURSOR_THEME_VALUE="${XCURSOR_THEME:-}"
    HYPRCURSOR_SIZE_VALUE="${HYPRCURSOR_SIZE:-24}"
    HYPRCURSOR_THEME_VALUE="${HYPRCURSOR_THEME:-}"
    QT_QPA_PLATFORMTHEME_VALUE="${QT_QPA_PLATFORMTHEME:-}"
    WLR_NO_HARDWARE_CURSORS_VALUE="${WLR_NO_HARDWARE_CURSORS:-}"

    # Launch Nuke in namespace as the actual user
    # We need to preserve X11/Wayland environment for GUI
    ip netns exec "$NAMESPACE" sudo -u "$ACTUAL_USER" \
        env DISPLAY="$DISPLAY_VALUE" \
        XAUTHORITY="$XAUTHORITY_PATH" \
        HOME="/home/$ACTUAL_USER" \
        USER="$ACTUAL_USER" \
        WAYLAND_DISPLAY="$WAYLAND_DISPLAY_VALUE" \
        XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR_VALUE" \
        XCURSOR_SIZE="$XCURSOR_SIZE_VALUE" \
        XCURSOR_THEME="$XCURSOR_THEME_VALUE" \
        HYPRCURSOR_SIZE="$HYPRCURSOR_SIZE_VALUE" \
        HYPRCURSOR_THEME="$HYPRCURSOR_THEME_VALUE" \
        QT_QPA_PLATFORMTHEME="$QT_QPA_PLATFORMTHEME_VALUE" \
        WLR_NO_HARDWARE_CURSORS="$WLR_NO_HARDWARE_CURSORS_VALUE" \
        "$NUKE_EXECUTABLE" "$@" &

    NUKE_PID=$!

    log "${GREEN}Nuke launched (PID: $NUKE_PID)${NC}"
    log ""
    log "Monitoring network isolation..."
    log "Press Ctrl+C to stop monitoring (Nuke will keep running)"
    log ""

    # Monitor for 10 seconds to verify isolation
    for i in {1..10}; do
        sleep 1

        # Check if Nuke is still running
        if ! kill -0 "$NUKE_PID" 2>/dev/null; then
            log "${RED}Nuke exited unexpectedly${NC}"
            log "Check for errors in Nuke's output or logs"
            cleanup_namespace
            exit 1
        fi

        # Verify no external connections
        EXTERNAL_CONNS=$(ip netns exec "$NAMESPACE" ss -tnp 2>/dev/null | grep -v "127.0.0.1" | grep "ESTAB" || true)

        if [ -n "$EXTERNAL_CONNS" ]; then
            log "${RED}WARNING: External connection detected!${NC}"
            echo "$EXTERNAL_CONNS"
        else
            echo -n "."
        fi
    done

    log ""
    log ""
    log "${GREEN}✓ Nuke is running in isolated namespace${NC}"
    log ""
    log "Useful commands:"
    log "  Check namespace status: sudo bash $0 --status"
    log "  View Nuke connections:  sudo ip netns exec $NAMESPACE ss -tnp | grep Nuke"
    log "  Kill Nuke:              kill $NUKE_PID"
    log "  Cleanup namespace:      sudo bash $0 --cleanup"
    log ""
    log "Note: Namespace will be automatically cleaned up when Nuke exits"
    log "      If Nuke crashes, run: sudo bash $0 --cleanup"

    # Wait for Nuke to exit, then cleanup
    wait "$NUKE_PID" 2>/dev/null || true
    log ""
    log "${YELLOW}Nuke exited, cleaning up namespace...${NC}"
    cleanup_namespace
    log "${GREEN}Cleanup complete${NC}"
}

main() {
    check_root

    if [ "$1" = "--cleanup" ] || [ "$1" = "--clean" ]; then
        cleanup_namespace

    elif [ "$1" = "--status" ]; then
        show_status

    elif [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
        log "Nuke Network Namespace Isolation Launcher"
        log ""
        log "Usage:"
        log "  sudo bash $0 [NUKE_ARGS]  Launch Nuke in isolated namespace"
        log "  sudo bash $0 --cleanup    Clean up namespace"
        log "  sudo bash $0 --status     Check namespace status"
        log "  sudo bash $0 --help       Show this help"
        log ""
        log "Examples:"
        log "  sudo bash $0              Launch Nuke normally"
        log "  sudo bash $0 --nukex      Launch NukeX"
        log "  sudo bash $0 --nc         Launch in non-commercial mode"
        log ""
        log "What this does:"
        log "  - Creates a network namespace with ONLY loopback interface"
        log "  - Launches Nuke inside the namespace"
        log "  - Blocks ALL external network access (no telemetry possible)"
        log "  - Preserves localhost (127.0.0.1) for frameserver communication"
        log "  - Preserves Wayland/Hyprland display settings (cursor theme/size)"
        log ""
        log "Configuration:"
        log "  Nuke executable: $NUKE_EXECUTABLE"
        log "  Namespace name:  $NAMESPACE"

    else
        check_nuke_exists
        # Pass all arguments to launch_nuke, which will forward them to Nuke
        launch_nuke "$@"
    fi
}

main "$@"
