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

def getIp(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    ip= fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24]

    info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', ifname[:15]))
    hwaddr = ':'.join(['%02x' % ord(char) for char in info[18:24]])

    return ip, hwaddr


oldNicTrafficMap = None
import psutil
def GetNicUtil():
    global oldNicTrafficMap
    kstatMap = {}

    kstatMap = psutil.net_io_counters(pernic=True)
    nicTrafficMap = {}

    ipinfo = {}
    ipmpList = set()
    ipmpMemberList = set()
    #try:
    if True:
        ifconfig = process_util.executeCmd('ifconfig -a')
        deviceId = None
        for l in ifconfig.split('\n'):
            if not l:
                continue
            token = l.split()
            if token[0].endswith(':'):
                deviceId = token[0].split(':')[0]
                if deviceId not in ipinfo:
                    ipinfo[deviceId] = {}
            elif token[0] == 'inet':
                ip = token[1]
                ipinfo[deviceId]['ip'] = ip
            elif token[0] == 'ether':
                hwaddr = token[1]
                ipinfo[deviceId]['hwaddr'] = hwaddr
            elif token[0] == 'groupname':
                groupname = token[1]
                ipmpList.add(groupname)
                if groupname != deviceId:
                    ipmpMemberList.add(deviceId)
                
    #except Exception, e:
    #    pass

    timestamp = time.time()
    traffics = []

    for deviceId, v in kstatMap.items():
        nicTrafficIoRaw = _NetPerfRaw()
        nicTrafficIoRaw.deviceId = deviceId
        nicTrafficIoRaw.readByteCount = int(v.bytes_recv)
        nicTrafficIoRaw.readCount = int(v.packets_recv)
        nicTrafficIoRaw.readErrorCount = int(v.errin)
        nicTrafficIoRaw.readDroppedCount = int(v.dropin)
        nicTrafficIoRaw.writeByteCount = int(v.bytes_sent)
        nicTrafficIoRaw.writeCount = int(v.packets_sent)
        nicTrafficIoRaw.writeErrorCount = int(v.errout)
        nicTrafficIoRaw.writeDroppedCount = int(v.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 * 8
            n.trafficOut = float(nicTrafficIoRaw.writeByteCount - oldNicTrafficIoRaw.writeByteCount) / timediff * 8
            n.packetIn = float(nicTrafficIoRaw.readCount - oldNicTrafficIoRaw.readCount) / timediff 
            n.packetOut = float(nicTrafficIoRaw.writeCount - oldNicTrafficIoRaw.writeCount) / timediff
            n.droppedIn = float(nicTrafficIoRaw.readDroppedCount - oldNicTrafficIoRaw.readDroppedCount) / timediff
            n.droppedOut = float(nicTrafficIoRaw.writeDroppedCount - oldNicTrafficIoRaw.writeDroppedCount) / timediff
            n.errorIn = float(nicTrafficIoRaw.readErrorCount - oldNicTrafficIoRaw.readErrorCount) / timediff
            n.errorOut = float(nicTrafficIoRaw.writeErrorCount - oldNicTrafficIoRaw.writeErrorCount) / timediff
            if deviceId not in ipinfo or deviceId in ipmpMemberList or 'ip' not in ipinfo[deviceId]:
                continue
            n.ip = ip_util.toBytes(ipinfo[deviceId]['ip'])
            if 'hwaddr' not in ipinfo[deviceId]:
                n.hwAddr = ""
            else:
                n.hwAddr = ipinfo[deviceId]['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, oldTime = oldNetInfo 

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

    oldNetInfo = (net, now)
    return n


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

if __name__ == '__main__':
    test()
