import psutil
import os, time
import socket, fcntl, struct
import whatap.util.process_util as process_util
from whatap.util.hash_util import HashUtil as hash
from whatap.util.ip_util import IPUtil as ip_util
from whatap.pack.pack_enum import PackEnum
import whatap.pack.smnetperf_pack as smnetperf_pack
from StringIO import StringIO

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()

_nicInfoDict = {}

def getNicInfo(deviceId):
    
    if deviceId not in _nicInfoDict:
        addrs = psutil.net_if_addrs()
        if deviceId not in addrs or not addrs[deviceId]:
            return None, None
        nicip = addrs[deviceId][0].address
        hwaddr = None
        entstat = process_util.executeCmd('entstat -d %s'%(deviceId))
        for l in entstat.split('\n'):
            l = l.strip()
            if l and l.startswith('Hardware Address:'):
                hwaddr = l.split(':')[1].strip()
                break
        if not hwaddr:
            return None, None
        _nicInfoDict[deviceId] = (nicip, hwaddr)
        
    nicip, hwaddr = _nicInfoDict[deviceId]

    return nicip, hwaddr

oldNicTrafficMap = None
def GetNicUtil():
    global oldNicTrafficMap
    iocounters = psutil.net_io_counters(pernic=True)
    
    nicTrafficMap = {}

    timestamp = int(time.time() * 1000)
    traffics = []
    j =0
    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()
