#!/usr/bin/env bash
# Pick a nearby WiFi network in wofi and connect to it through wpa_supplicant
# (userControlled: the control socket is open to wheel).  Networks added here
# live in wpa_supplicant's memory only — the config file is a sops secret and
# is never rewritten — so they are gone after a reboot.
detach_self "$@"

eww close popup 2>/dev/null
eww update active-panel= 2>/dev/null

iface=""
for s in /run/wpa_supplicant/*; do
  [[ -S $s && ${s##*/} != p2p-* ]] && { iface=${s##*/}; break; }
done

notify() { notify-send -a WiFi -i network-wireless "$@"; }
[[ -n $iface ]] || { notify "WiFi" "wpa_supplicant is not running"; exit 1; }

wpa() { wpa_cli -g "/run/wpa_supplicant/$iface" "$@"; }
field() { awk -F= -v k="$1" '$1 == k { print substr($0, length(k) + 2); exit }'; }

signal_icon() {
  if (($1 >= -50)); then echo "󰤨"
  elif (($1 >= -60)); then echo "󰤥"
  elif (($1 >= -70)); then echo "󰤢"
  elif (($1 >= -80)); then echo "󰤟"
  else echo "󰤯"; fi
}

# wpa_cli prints SSIDs with printf-style escapes (\xNN, \\, \")
unescape() { printf '%b' "$1"; }

saved_id() { # SSID → network id
  local id s
  while IFS=$'\t' read -r id s _; do
    [[ $(unescape "$s") == "$1" ]] && { echo "$id"; return; }
  done < <(wpa list_networks | tail -n +2)
}

wpa scan >/dev/null
sleep 2

current=$(unescape "$(wpa status | field ssid)")

declare -A ssid_of flags_of
lines=()
# strongest BSS per SSID, strongest first; hidden networks are skipped
while IFS=$'\t' read -r sig flags raw; do
  ssid=$(unescape "$raw")
  [[ -n $ssid && $ssid != *$'\n'* ]] || continue
  line="$(signal_icon "$sig")  $ssid"
  [[ $flags == *PSK* || $flags == *SAE* || $flags == *EAP* ]] && line+="  󰌾"
  [[ $ssid == "$current" ]] && line+="  󰄬"
  ssid_of[$line]=$ssid
  flags_of[$line]=$flags
  lines+=("$line")
done < <(wpa scan_results | awk -F'\t' '
  NR > 1 && $5 != "" { if (!($5 in best) || $3 > best[$5]) { best[$5] = $3; flags[$5] = $4 } }
  END { for (s in best) printf "%s\t%s\t%s\n", best[s], flags[s], s }' | sort -t$'\t' -k1,1nr)

((${#lines[@]})) || { notify "WiFi" "No networks found"; exit 0; }

choice=$(printf '%s\n' "${lines[@]}" | wofi --dmenu -p "WiFi")
[[ -n $choice && -n ${ssid_of[$choice]+x} ]] || exit 0
ssid=${ssid_of[$choice]}
flags=${flags_of[$choice]}
[[ $ssid == "$current" ]] && exit 0

id=$(saved_id "$ssid")
new=0
if [[ -z $id ]]; then
  [[ $flags == *EAP* ]] && { notify "$ssid" "Enterprise (EAP) networks are not supported"; exit 1; }
  id=$(wpa add_network | tail -n 1)
  [[ $id =~ ^[0-9]+$ ]] || { notify "$ssid" "Could not add the network"; exit 1; }
  new=1
  wpa set_network "$id" ssid "$(printf '%s' "$ssid" | od -An -tx1 | tr -d ' \n')" >/dev/null
  if [[ $flags == *PSK* || $flags == *SAE* ]]; then
    psk=$(wofi --dmenu --password -p "Password for $ssid" </dev/null)
    if ((${#psk} < 8 || ${#psk} > 63)); then
      wpa remove_network "$id" >/dev/null
      [[ -n $psk ]] && notify "$ssid" "The password must be 8 to 63 characters"
      exit 1
    fi
    wpa set_network "$id" psk "\"$psk\"" >/dev/null
    if [[ $flags == *SAE* ]]; then
      wpa set_network "$id" key_mgmt WPA-PSK SAE >/dev/null
      wpa set_network "$id" ieee80211w 1 >/dev/null
    fi
  else
    wpa set_network "$id" key_mgmt NONE >/dev/null
  fi
fi

# select_network disables every other network; re-enable them afterwards so
# the saved ones still auto-connect later.
wpa select_network "$id" >/dev/null
for ((i = 0; i < 30; i++)); do
  sleep 0.5
  st=$(wpa status)
  if [[ $(field wpa_state <<<"$st") == COMPLETED && $(field id <<<"$st") == "$id" ]]; then
    wpa enable_network all >/dev/null
    notify "Connected" "$ssid"
    exit 0
  fi
done

((new)) && wpa remove_network "$id" >/dev/null
wpa enable_network all >/dev/null
wpa reassociate >/dev/null
notify "Could not connect to $ssid" "$( ((new)) && echo "Wrong password?" || echo "Timed out")"
exit 1
