import psutil
import time
import whatap.util.process_util as process_util
from whatap.util.ip_util import IPUtil as ip_util
import whatap.util.logging_util as logging_util

class _NetPerfRaw:
    def __init__(self):
        self.deviceID = None
        self.readCount = None
        self.readByteCount = None
        self.readDroppedCount = None
        self.readErrorCount = None
        self.writeCount = None
        self.writeByteCount = None
        self.writeDroppedCount = None
        self.writeErrorCount = None
        self.timestamp = None

class _NetPerf:
    def __init__(self):
        self.desc = None
        self.ip = None
        self.hwAddr = None
        self.trafficIn = None
        self.trafficOut = None
        self.packetIn = None
        self.packetOut = None
        self.errorIn = None
        self.errorOut =  None
        self.droppedOut = None
        self.droppedIn = None

    def __str__(self):
        buf = StringIO()
        buf.write('\ndesc=')
        buf.write(self.desc)
        buf.write('\nip=')
        buf.write(self.ip)
        buf.write('\nhwAddr=')
        buf.write(self.hwAddr)
        buf.write('\ntrafficIn=')
        buf.write(self.trafficIn)
        buf.write('\ntrafficOut=')
        buf.write(self.trafficOut)
        buf.write('\npacketIn=')
        buf.write(self.packetIn)
        buf.write('\npacketOut=')
        buf.write(self.packetOut)
        buf.write('\nerrorIn=')
        buf.write(str(self.errorIn))
        buf.write('\nerrorOut=')
        buf.write(str(self.errorOut))
        buf.write('\ndroppedOut=')
        buf.write(str(self.droppedOut))
        buf.write('\ndroppedIn=')
        buf.write(str(self.droppedIn))

        return buf.getvalue()



oldNicTrafficMap = None
nicInfoDict = {}
macDict = {}



def getNicInfo(deviceId):
    global nicInfoDict
    ip = ""
    mac = ""
    if deviceId not in nicInfoDict:
        ifconfig = process_util.executeCmd('ifconfig ' + deviceId)

        for l in ifconfig.split('\n'):
            if not l:
                continue
            token = l.split()
            if token[0] == 'inet':
                ip = token[1]
                break

        if deviceId not in macDict:
            lanscan = process_util.executeCmd('lanscan -ai')
            for l in lanscan.split('\n'):
                if not l:
                    continue
                token = l.split()
                if not token[0].startswith('0x'):
                    continue

                macValue = token[0][2:]
                macValue = macValue.zfill(12)
                macArr = [macValue[i:i+2] for i in range(0, len(macValue), 2)]

                formattedMac = ":".join(macArr)
                
                macDict[token[1]] = formattedMac 
                mac = formattedMac

        else:
            mac = macDict[deviceId]

        info = (ip, mac)
        nicInfoDict[deviceId] = info

    nicip, hwaddr = nicInfoDict[deviceId]
    return nicip, hwaddr



def GetNicUtil():
    global oldNicTrafficMap
    logging_util.debug("[network] start net_io_counters")
    iocounters = psutil.net_io_counters(pernic=True)
    logging_util.debug("[network] end net_io_counters - len : ", len(iocounters))

    nicTrafficMap = {}

    timestamp = int(time.time() * 1000)

    traffics = []
    for deviceId, iocounter in iocounters.items():
        nicTrafficIoRaw = _NetPerfRaw()
        nicTrafficIoRaw.deviceID = deviceId
        nicTrafficIoRaw.readByteCount = int(iocounter.bytes_recv)
        nicTrafficIoRaw.readCount = int(iocounter.packets_recv)
        nicTrafficIoRaw.readErrorCount = int(iocounter.errin)
        nicTrafficIoRaw.readDroppedCount = int(iocounter.dropin)
        nicTrafficIoRaw.writeByteCount = int(iocounter.bytes_sent)
        nicTrafficIoRaw.writeCount = int(iocounter.packets_sent)
        nicTrafficIoRaw.writeErrorCount = int(iocounter.errout)
        nicTrafficIoRaw.writeDroppedCount = int(iocounter.dropout)
        nicTrafficIoRaw.timestamp = timestamp

 
        nicTrafficMap[deviceId] = nicTrafficIoRaw 

        if oldNicTrafficMap and deviceId in oldNicTrafficMap:
            oldNicTrafficIoRaw = oldNicTrafficMap[deviceId]
            timediff = nicTrafficIoRaw.timestamp - oldNicTrafficIoRaw.timestamp
            n = _NetPerf()
            n.desc = deviceId
            n.trafficIn = float(nicTrafficIoRaw.readByteCount - oldNicTrafficIoRaw.readByteCount) / timediff * 1000.0 * 8
            n.trafficOut = float(nicTrafficIoRaw.writeByteCount - oldNicTrafficIoRaw.writeByteCount) / timediff * 1000.0 * 8
            n.packetIn = float(nicTrafficIoRaw.readCount - oldNicTrafficIoRaw.readCount) / timediff * 1000.0
            n.packetOut = float(nicTrafficIoRaw.writeCount - oldNicTrafficIoRaw.writeCount) / timediff * 1000.0
            n.droppedIn = float(nicTrafficIoRaw.readDroppedCount - oldNicTrafficIoRaw.readDroppedCount) / timediff * 1000.0
            n.droppedOut = float(nicTrafficIoRaw.writeDroppedCount - oldNicTrafficIoRaw.writeDroppedCount) / timediff * 1000.0
            n.errorIn = float(nicTrafficIoRaw.readErrorCount - oldNicTrafficIoRaw.readErrorCount) / timediff * 1000.0
            n.errorOut = float(nicTrafficIoRaw.writeErrorCount - oldNicTrafficIoRaw.writeErrorCount) / timediff * 1000.0
            nicip, hwaddr = getNicInfo(deviceId)
            if not nicip or not hwaddr:
                continue
            n.ip = ip_util.toBytes(nicip)
            n.hwAddr = hwaddr

            traffics.append(n)



    oldNicTrafficMap = nicTrafficMap

    return traffics
    

oldNetInfo = None
def GetNetInfo():
    now = time.time()
    net = psutil.net_io_counters()

    global oldNetInfo
    if not oldNetInfo:
        oldNetInfo = [net, now]
        return None

    oldNet = oldNetInfo[0]
    diffTime  = now - oldNetInfo[1]

    n = _NetPerf()

    n.trafficIn = float(net.bytes_recv - oldNet.bytes_recv) / diffTime * 8
    n.trafficOut = float(net.bytes_sent - oldNet.bytes_sent) / diffTime * 8
    n.packetIn = float(net.packets_recv - oldNet.packets_recv) / diffTime 
    n.packetOut = float(net.packets_sent - oldNet.packets_sent) /diffTime

    oldNetInfo = [net, now]
    return n

def test():
    print 'test'
    print GetNicUtil()
    time.sleep(5)
    for netperf in GetNicUtil():
        print netperf

if __name__ == '__main__':
    test()
