#!/bin/bash

# =======================================================
# ============= Ultimate Wake On Lan v1.3 ===============
# =======================================================
# Adds a fully automatic scan/wake mode and more output.
#
# USAGE:
# Make it executable: chmod +x wakeup.sh
# Run with sudo:      sudo ./wakeup.sh

# --- Configuration ---
NETWORK="192.168.1.0/24"
KNOWN_HOSTS_FILE="${HOME}/.wol_known_hosts"

# --- Color Definitions ---
RED='\033[0;31m'
L_RED='\033[1;31m'
GREEN='\033[0;32m'
L_GREEN='\033[1;32m'
YELLOW='\033[0;33m'
L_YELLOW='\033[1;33m'
BLUE='\033[0;34m'
L_BLUE='\033[1;34m'
MAGENTA='\033[0;35m'
L_MAGENTA='\033[1;35m'
CYAN='\033[0;36m'
L_CYAN='\033[1;36m'
WHITE='\033[1;37m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# --- Core Functions ---

check_tools() {
  local missing_tools=0
  for tool in "$@"; do
    if ! command -v "$tool" &> /dev/null; then echo -e "${RED}Error: Required command '${BOLD}$tool${RED}' is not installed.${NC}"; missing_tools=1; fi
  done
  if [ $missing_tools -ne 0 ]; then
    echo -e "\n${YELLOW}Please install the missing tools to proceed.${NC}"; echo "On Debian/Ubuntu: ${CYAN}sudo apt-get install nmap wakeonlan${NC}"; echo "On Fedora/CentOS: ${CYAN}sudo dnf install nmap wakeonlan${NC}"; exit 1
  fi
}

scan_network() {
  local nmap_flags="$1"
  echo -e "---------------------------------------------------------"
  echo -e "${CYAN}Starting network scan on ${BOLD}${NETWORK}${CYAN} with flags: ${BOLD}${nmap_flags}${NC}"
  echo -e "${YELLOW}Displaying nmap output live. This may take a while.${NC}"
  echo -e "---------------------------------------------------------"
  
  local nmap_output_file=$(mktemp)
  local start_time=$(date +%s)
  
  # Increased verbosity to -vv for more output
  nmap -vv ${nmap_flags} "${NETWORK}" | tee "$nmap_output_file"
  
  local end_time=$(date +%s)
  local duration=$((end_time - start_time))
  
  echo -e "---------------------------------------------------------"
  echo -e "${GREEN}Parsing results...${NC}"
  
  local devices
  devices=$(awk -v ip_color="$L_GREEN" -v mac_color="$L_CYAN" -v nc="$NC" \
      '/Nmap scan report for/{ip=$5} /MAC Address:/{mac=$3; vendor=substr($0, index($0,$4)); printf "%s%s%s %s%s%s %s\n", ip_color, ip, nc, mac_color, mac, nc, vendor}' "$nmap_output_file")
  
  local device_count
  # Use xargs to trim whitespace from wc -l output
  device_count=$(echo "$devices" | wc -l | xargs)

  echo -e "${L_GREEN}${BOLD}Scan Complete.${NC} Found ${WHITE}${BOLD}${device_count}${NC} devices in ${WHITE}${BOLD}${duration}${NC} seconds."
  echo -e "---------------------------------------------------------"

  rm "$nmap_output_file"
  # Return the found devices for further action
  echo "$devices"
}

wake_device() {
  local mac=$1
  echo -e "\n${MAGENTA}Sending Wake-on-LAN packet to ${L_CYAN}${BOLD}${mac}${MAGENTA}...${NC}"
  wakeonlan "${mac}"; echo -e "${GREEN}Packet sent.${NC}"
}

# --- Menu Functions ---

action_menu() {
  local devices="$1"
  echo -e "${BLUE}${BOLD}--- Scan Results ---${NC}"
  echo -e "${WHITE}$(echo -e "$devices" | cat -n)${NC}"
  read -p "Save these devices to the known hosts list? (y/N): " save_choice
  if [[ "$save_choice" =~ ^[Yy]$ ]]; then
    touch "$KNOWN_HOSTS_FILE"
    echo -e "$devices" | sed -r 's/\x1b\[[0-9;]*m//g' | while read -r device_line; do
      local mac=$(echo "$device_line" | awk '{print $2}'); if ! grep -qF "$mac" "$KNOWN_HOSTS_FILE"; then echo "$device_line" >> "$KNOWN_HOSTS_FILE"; echo -e "${GREEN}Saved:${NC} $device_line"; fi
    done
  fi
  PS3=$(echo -e "\n${YELLOW}Please choose an action: ${NC}")
  local action_options=("Wake a Specific Device from Scan" "Wake All Devices from Scan" "Done")
  select action in "${action_options[@]}"; do
    case $action in
      "Wake a Specific Device from Scan")
        local device_options; mapfile -t device_options <<< "$devices"; device_options+=("Cancel")
        PS3=$(echo -e "${YELLOW}Enter number of device to wake: ${NC}")
        select choice in "${device_options[@]}"; do
          if [[ "$choice" == "Cancel" ]]; then break; fi; if [[ -n "$choice" ]]; then wake_device "$(echo -e "$choice" | sed -r 's/\x1b\[[0-9;]*m//g' | awk '{print $2}')"; break; else echo -e "${RED}Invalid selection.${NC}"; fi
        done; break ;;
      "Wake All Devices from Scan") echo -e "$devices" | sed -r 's/\x1b\[[0-9;]*m//g' | awk '{print $2}' | while read -r mac; do wake_device "$mac"; done; break ;;
      "Done") break ;;
      *) echo -e "${RED}Invalid option $REPLY${NC}" ;;
    esac
  done
}

timing_menu() {
  local profile_flags="$1"
  echo -e "${L_BLUE}${BOLD}--- Step 2: Choose Scan Speed ---${NC}"
  PS3=$(echo -e "\n${YELLOW}Aggressive (T4) is best for fast networks. Use Polite (T2) if you see errors.${NC}\nSelect a timing template: ")
  local timing_options=("Paranoid (T0)" "Sneaky (T1)" "Polite (T2)" "Normal (T3)" "Aggressive (T4)" "Insane (T5)" "Cancel")
  select timing_choice in "${timing_options[@]}"; do
    local timing_flag=""; case $timing_choice in "Paranoid (T0)") timing_flag="-T0";; "Sneaky (T1)") timing_flag="-T1";; "Polite (T2)") timing_flag="-T2";; "Normal (T3)") timing_flag="-T3";; "Aggressive (T4)") timing_flag="-T4";; "Insane (T5)") timing_flag="-T5";; "Cancel") return;; *) echo -e "${RED}Invalid option $REPLY${NC}"; continue;; esac
    local devices; devices=$(scan_network "${profile_flags} ${timing_flag}")
    if [ -z "$devices" ]; then echo -e "${YELLOW}No devices with discoverable MAC addresses were found.${NC}"; else action_menu "$devices"; fi
    break
  done
}

scan_profile_menu() {
  echo -e "${L_BLUE}${BOLD}--- Step 1: Choose Scan Profile ---${NC}"
  PS3=$(echo -e "\n${YELLOW}Select what you want to find: ${NC}")
  local profile_options=("Simple Host List (for WOL)" "Quick Port Scan" "Full TCP Port Scan" "Aggressive Scan (OS, Version)" "Back to Main Menu")
  select opt in "${profile_options[@]}"; do
    local nmap_params=""; case $opt in "Simple Host List (for WOL)") nmap_params="-sn";; "Quick Port Scan") nmap_params="-F";; "Full TCP Port Scan") nmap_params="-p-";; "Aggressive Scan (OS, Version)") nmap_params="-A";; "Back to Main Menu") return;; *) echo -e "${RED}Invalid option $REPLY${NC}"; continue;; esac
    timing_menu "$nmap_params"; break
  done
}

automatic_wake_all() {
  echo -e "${L_BLUE}${BOLD}--- Automatic Scan & Wake All ---${NC}"
  # Use the fastest, most reliable scan for finding WOL-ready hosts on a LAN.
  local nmap_params="-sn -T4"
  local devices
  devices=$(scan_network "$nmap_params")

  if [ -z "$devices" ]; then
    echo -e "\n${YELLOW}No devices were found to wake up.${NC}"
  else
    echo -e "\n${GREEN}Waking up all discovered devices...${NC}"
    # Extract just the MAC address (2nd column after stripping colors) and wake each one
    echo -e "$devices" | sed -r 's/\x1b\[[0-9;]*m//g' | awk '{print $2}' | while read -r mac; do
      wake_device "$mac"
    done
    echo -e "\n${GREEN}${BOLD}All WOL packets have been sent!${NC}"
  fi
}

direct_wake_menu() { # (Unchanged)
  echo -e "${L_MAGENTA}${BOLD}--- Direct Wake ---${NC}"; read -p "Enter the MAC address to wake: " mac_address
  if [[ "$mac_address" =~ ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$ ]]; then wake_device "$mac_address"; else echo -e "${RED}Invalid MAC address format.${NC}"; fi
}

change_network_menu() { # (Unchanged)
  echo -e "${L_MAGENTA}${BOLD}--- Change Network Target ---${NC}"; echo -e "Current network target is: ${L_CYAN}${NETWORK}${NC}"
  read -p "Enter new network target in CIDR format (e.g., 10.0.0.0/24): " new_network
  if [ -n "$new_network" ]; then NETWORK="$new_network"; echo -e "${GREEN}Network target updated to ${BOLD}${NETWORK}${NC} for this session."; else echo -e "${RED}No input provided.${NC}"; fi
}

saved_hosts_menu() { # (Unchanged)
  echo -e "${L_MAGENTA}${BOLD}--- Wake from Saved List ---${NC}"
  if [[ ! -f "$KNOWN_HOSTS_FILE" || ! -s "$KNOWN_HOSTS_FILE" ]]; then echo -e "${YELLOW}Known hosts file is empty.${NC}"; return; fi
  echo -e "${WHITE}Available saved hosts:${NC}"; awk -v ip_color="$L_GREEN" -v mac_color="$L_CYAN" -v nc="$NC" '{printf "%s%s%s %s%s%s %s\n", ip_color, $1, nc, mac_color, $2, nc, substr($0, index($0,$3))}' "$KNOWN_HOSTS_FILE" | cat -n
  PS3=$(echo -e "\n${YELLOW}Choose an option for saved hosts: ${NC}"); local saved_options=("Wake a Specific Saved Host" "Wake ALL Saved Hosts" "Delete a Saved Host" "Cancel")
  select opt in "${saved_options[@]}"; do
    case $opt in
      "Wake a Specific Saved Host"|"Delete a Saved Host") local device_options; mapfile -t device_options < "$KNOWN_HOSTS_FILE"; device_options+=("Cancel"); PS3=$(echo -e "${YELLOW}Select a host to ${opt// a Saved Host/}: ${NC}"); select choice in "${device_options[@]}"; do if [[ "$choice" == "Cancel" ]]; then break; fi; if [[ -n "$choice" ]]; then if [[ "$opt" == "Wake a Specific Saved Host" ]]; then wake_device "$(echo "$choice" | awk '{print $2}')"; else grep -vFw "$choice" "$KNOWN_HOSTS_FILE" > "$KNOWN_HOSTS_FILE.tmp" && mv "$KNOWN_HOSTS_FILE.tmp" "$KNOWN_HOSTS_FILE"; echo -e "${GREEN}Deleted entry:${NC} $choice"; fi; break; else echo -e "${RED}Invalid selection.${NC}"; fi; done; break ;;
      "Wake ALL Saved Hosts") awk '{print $2}' "$KNOWN_HOSTS_FILE" | while read -r mac; do wake_device "$mac"; done; break ;;
      "Cancel") break ;;
      *) echo -e "${RED}Invalid option $REPLY${NC}";;
    esac
  done
}

help_menu() {
    echo -e "${L_MAGENTA}${BOLD}--- Help & Information ---${NC}"
    echo -e "Welcome to the ${BOLD}Ultimate Wake On Lan${NC} script (v1.3)."
    echo -e "\n${BOLD}Menu Options:${NC}"
    echo -e "  ${L_RED}Automatic Scan & Wake:${NC} The express option. Immediately scans for all devices"
    echo -e "                       on the network and sends a WOL packet to each one."
    echo -e "  ${L_GREEN}Manual Scan Network:${NC}   Provides full control over the scan. You first choose a"
    echo -e "                       Scan Profile (what to look for), then a Timing Template"
    echo -e "                       (how fast to scan)."
    echo -e "  ${L_CYAN}Saved & Direct Wake:${NC} Wake devices from your saved list or by entering a"
    echo -e "                       MAC address manually."
    echo -e "\n${BOLD}Scan Timing (-T0 to -T5):${NC}"
    echo -e "  If you get ${L_RED}timeout errors${NC}, your network can't keep up. Slow down the scan!"
    echo -e "  ${L_GREEN}-T4 (Aggressive):${NC} Recommended for fast, modern LANs."
    echo -e "  ${L_YELLOW}-T3 (Normal):${NC}      Nmap's default behavior."
    echo -e "  ${L_RED}-T2 (Polite):${NC}       Slower scan that uses less bandwidth. Try this if T4/T3 fail."
}

main_menu() {
  while true; do
    echo -e "${L_RED}${BOLD}U${L_YELLOW}l${L_GREEN}t${L_CYAN}i${L_BLUE}m${L_MAGENTA}a${L_RED}t${L_YELLOW}e ${L_GREEN}W${L_CYAN}a${L_BLUE}k${L_MAGENTA}e ${L_RED}O${L_YELLOW}n ${L_GREEN}L${L_CYAN}a${L_BLUE}n${NC} ${WHITE}v1.3${NC}"
    echo -e "${BLUE}=======================================================${NC}"
    echo -e "  Network Target: ${L_CYAN}${BOLD}${NETWORK}${NC}"
    echo -e "${BLUE}=======================================================${NC}"

    PS3=$(echo -e "\n${WHITE}${BOLD}Select an option: ${NC}")
    local options=(
      "$(echo -e "${L_RED}🚀${NC} Automatic Scan & Wake All")"
      "$(echo -e "${L_GREEN}★${NC} Manual Scan Network")"
      "$(echo -e "${L_CYAN}★${NC} Wake from Saved List")"
      "$(echo -e "${L_BLUE}★${NC} Wake a MAC Address Directly")"
      "$(echo -e "${L_MAGENTA}★${NC} Change Network Target")"
      "$(echo -e "${L_YELLOW}★${NC} Help & Information")"
      "$(echo -e "${WHITE}★${NC} Exit")"
    )
    select opt in "${options[@]}"; do
      local clean_opt; clean_opt=$(echo "$opt" | sed -r 's/\x1b\[[0-9;]*m//g' | sed -r 's/🚀 |★ //g')
      case "$clean_opt" in
        "Automatic Scan & Wake All") automatic_wake_all; break ;;
        "Manual Scan Network") scan_profile_menu; break ;;
        "Wake from Saved List") saved_hosts_menu; break ;;
        "Wake a MAC Address Directly") direct_wake_menu; break ;;
        "Change Network Target") change_network_menu; break ;;
        "Help & Information") help_menu; break ;;
        "Exit") echo -e "${GREEN}Exiting. Goodbye!${NC}"; exit 0 ;;
        *) echo -e "${RED}Invalid option $REPLY. Please choose a number from the list.${NC}" ;;
      esac
    done
    echo -e "\n${YELLOW}Press any key to return to the main menu...${NC}"
    read -n 1 -s -r
    clear
  done
}

# --- Script Start ---
clear
check_tools "nmap" "wakeonlan"
if [ "$EUID" -ne 0 ]; then echo -e "${RED}${BOLD}Root Access Required${NC}\n${YELLOW}Please run with sudo for best results.${NC}"; exit 1; fi
main_menu