#!/bin/bash
# Emit the full network state as one JSON line for eww.
# Replaces wifi-monitor, wifi-name-monitor and vpn-monitor.
#
# Output shape:
# {
#   "icon": "f",        # bar glyph: vpn / online / offline
#   "vpn": true,              # vpn connection is active
#   "vpnname": "asahi",
#   "vpnstate": "connected",  # connected | disconnected | missing
#   "wifi": true,
#   "ssid": "Mosenet",
#   "wifidev": "wld0",
#   "signal": 68,
#   "wired": false,
#   "wireddev": "",
#   "online": true,
#   "tooltip": "Wi-Fi: Mosenet"
# }

VPN_CONN="${VPN_CONN:-asahi}"

ICON_VPN="󱁍"     # vpn active
ICON_ONLINE="󰖟"  # connected, no vpn
ICON_OFFLINE="󰪎" # no connection

vpn_state() {
    if nmcli -t -f NAME connection show --active 2>/dev/null | grep -qx "$VPN_CONN"; then
        echo connected
    elif nmcli -t -f NAME connection show 2>/dev/null | grep -qx "$VPN_CONN"; then
        echo disconnected
    else
        echo missing
    fi
}

# First connected device of the given nmcli type. Prints "device<TAB>connection".
connected_device() {
    nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device 2>/dev/null |
        awk -F: -v want="$1" '$2 == want && $3 == "connected" { print $1 "\t" $4; exit }'
}

wifi_signal() {
    nmcli -t -f IN-USE,SIGNAL device wifi list --rescan no 2>/dev/null |
        awk -F: '/^\*/ { print $2; exit }'
}

emit_state() {
    local vpnstate vpn wifi_row wired_row
    local wifidev="" ssid="" signal=0 wireddev="" wiredconn=""
    local wifi=false wired=false online=false icon tooltip

    vpnstate=$(vpn_state)
    [ "$vpnstate" = connected ] && vpn=true || vpn=false

    wifi_row=$(connected_device wifi)
    if [ -n "$wifi_row" ]; then
        wifi=true
        wifidev=${wifi_row%%$'\t'*}
        ssid=${wifi_row#*$'\t'}
        signal=$(wifi_signal)
        [ -n "$signal" ] || signal=0
    fi

    wired_row=$(connected_device ethernet)
    if [ -n "$wired_row" ]; then
        wired=true
        wireddev=${wired_row%%$'\t'*}
        wiredconn=${wired_row#*$'\t'}
    fi

    if [ "$wifi" = true ] || [ "$wired" = true ]; then
        online=true
    fi

    if [ "$vpn" = true ]; then
        icon="$ICON_VPN"
    elif [ "$online" = true ]; then
        icon="$ICON_ONLINE"
    else
        icon="$ICON_OFFLINE"
    fi

    if [ "$wired" = true ]; then
        tooltip="Wired: $wiredconn"
    elif [ "$wifi" = true ]; then
        tooltip="Wi-Fi: $ssid"
    else
        tooltip="No connection"
    fi
    [ "$vpn" = true ] && tooltip="$tooltip  |  VPN $VPN_CONN up"

    jq -nc \
        --arg icon "$icon" \
        --argjson vpn "$vpn" \
        --arg vpnname "$VPN_CONN" \
        --arg vpnstate "$vpnstate" \
        --argjson wifi "$wifi" \
        --arg ssid "$ssid" \
        --arg wifidev "$wifidev" \
        --argjson signal "${signal:-0}" \
        --argjson wired "$wired" \
        --arg wireddev "$wireddev" \
        --arg wiredconn "$wiredconn" \
        --argjson online "$online" \
        --arg tooltip "$tooltip" \
        '$ARGS.named'
}

last=$(emit_state)
printf '%s\n' "$last"

# Report only real changes, so eww does not redraw on unrelated network events.
nmcli monitor | while read -r _; do
    current=$(emit_state)
    if [ "$current" != "$last" ]; then
        printf '%s\n' "$current"
        last=$current
    fi
done
