#!/usr/bin/python3

from subprocess import *
import subprocess
import sys
import re
import os.path
import json
from flexa_uci import *

def say( msg ):
    sys.stderr.write( msg + "\n" )
    subprocess.Popen( [ "logger -t \"wifi-core\" \"{}\"".format(msg) ] , shell=True )
    
KEY_STATE="state"
KEY_BSSID="bssid"
KEY_SSID="ssid"
KEY_MAC_ADDR="mac_address"
KEY_IP_ADDR="ip_address"

def getWpaCliInfo( statusInfo , wlanIf ):
    """
    Selected interface 'wlan0'
    bssid=00:06:91:d8:18:60
    freq=0
    ssid=BARIX
    id=0
    mode=station
    pairwise_cipher=CCMP
    group_cipher=TKIP
    key_mgmt=WPA2-PSK
    wpa_state=COMPLETED
    ip_address=192.168.1.43
    address=00:92:c5:0b:21:1c
    uuid=bc099ea9-8f4d-5434-9bf8-e74590516ce1
    """
    cliCmd      = "wpa_cli -p /var/run/wpa_supplicant -i {} status verbose".format(wlanIf)
    toolResults = check_output( [ cliCmd ] , shell=True ).decode("utf-8").splitlines()
    
    regexBssid      = re.compile(r"bssid=(.*)")
    regexSsid       = re.compile(r"ssid=(.*)")
    regexWpaState   = re.compile(r"wpa_state=(.*)")
    regexMacAddr    = re.compile(r"address=(.*)")
    regexIpAddr     = re.compile(r"ip_address=(.*)")
    # at the very least, ensure that a state is set on the output.
    statusInfo[KEY_STATE] = "Connecting"
    for line in toolResults:
        if re.search(regexBssid,line):
            match   = re.search(regexBssid,line)
            statusInfo[KEY_BSSID] = match.group(1)
        elif re.search(regexSsid,line):
            match   = re.search(regexSsid,line)
            statusInfo[KEY_SSID]  = match.group(1)
        elif re.search(regexIpAddr,line):
            match   = re.search(regexIpAddr,line)
            statusInfo[KEY_IP_ADDR]  = match.group(1)
        elif re.search(regexWpaState,line):
            match   = re.search(regexWpaState,line)
            wpaState= match.group(1)
            if wpaState=="COMPLETED":
                statusInfo[KEY_STATE] = "Connected"
            else:
                statusInfo[KEY_STATE] = "Connecting"    
        elif re.search(regexMacAddr,line):
            match   = re.search(regexMacAddr,line)
            statusInfo[KEY_MAC_ADDR]  = match.group(1).upper()
            
def getScanInfo( wlanIf ):
    """
    bssid / frequency / signal level / flags / ssid
    00:06:91:d8:18:60       2412    47      [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]       BARIX
    4a:5f:99:49:32:a8       2437    44      [WPA2-PSK-CCMP][WPS][ESS]       DIRECT-a8-HP M377 LaserJet
    a0:8c:f8:17:d4:30       2432    25      [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]       Vodafone-wl
    7c:c3:85:79:f4:c4       2462    23      [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]       CLEAN&RELAX
    00:06:91:d8:18:62       2412    44      [ESS]   MEO-WiFi
    """
    cliCmd      = "wpa_cli -p /var/run/wpa_supplicant -i {} scan_results".format(wlanIf)
    toolResults = check_output( [ cliCmd ] , shell=True ).decode("utf-8").splitlines()
    scanInfo    = list()
    regexEntry      = re.compile(r"^([0-9a-fA-F:]+)\s+(\d+)\s+(-?\d+)\s+(\[.*?\])\s+(.*)$") 
    for line in toolResults:
        if re.search(regexEntry,line):
            match       = re.search(regexEntry,line)
            entry       = dict()
            entry["bssid"] = match.group(1)
            entry["freq"]  = match.group(2)
            entry["rssi"]  = match.group(3)
            entry["ssid"]  = match.group(4)
            scanInfo.append( entry )
            #print( f"found entry: {entry}")
            
    return scanInfo


def getRssi( ssid ):
    file_path = '/tmp/barix-wifi/scan-results.json'
    
    # Check if the file exists
    if not os.path.exists(file_path):
        #print(f"Error: File {file_path} does not exist.")
        return None

    try:
        # Read and parse the JSON file
        with open(file_path, 'r') as file:
            data = json.load(file)

        # Search for the matching SSID
        for network in data.get('networks', []):
            #print(f"network[ssid]:{network['ssid']}, ssid:{ssid}")
            if network['ssid'] == ssid:
                return network['rssi']

        return None

    except json.JSONDecodeError as e:
        #print(f"Error: Invalid JSON:{e} ")
        return None
    except Exception as e:
        #print(f"An error occurred: {str(e)}")
        return None


if __name__ == "__main__":
    if len(sys.argv)<2 :
        say( """Incorrect parameters
            Usage:
                barix-wifi-status [args] WIFI_IF
            Arguments:
                --json    Format output in JSON
            """ )
        sys.exit(0)

    jsonOutput      = False
    for arg in sys.argv[1:-1]:
        if arg=="--json":
            jsonOutput  = True
        else:
            say( "Unknown argument: {}".format(arg) )
            sys.exit(1)
    
    wlanIf          = sys.argv[-1]    
    statusInfo      = dict()
    
    if not os.path.isdir( "/sys/class/net/{}".format(wlanIf) ):
        statusInfo[KEY_STATE] = "No dongle"
    else:
        if uci_get("network.wlan0.ssid")=="" or (uci_get("network.wlan0.security")=="WPA" and uci_get("network.wlan0.psk")=="" ) :
            statusInfo[KEY_STATE]   = "Not Configured"
        else:
            try:
                getWpaCliInfo(statusInfo,wlanIf)
            except:
                say("exception while checking for WPA CLI info. please check logs/config")
                statusInfo[KEY_STATE] = "Error"
            if statusInfo[KEY_STATE]=="Connected" :
                currentBssid    = statusInfo["ssid"]
                scanRssi = getRssi(currentBssid)
                statusInfo["rssi"]= "unknown"
                if scanRssi is not None:
                    statusInfo["rssi"]= scanRssi + "%"

    print( json.dumps(statusInfo, indent=4) )
    sys.exit(0)
                             
