import subprocess, shlex, os, time
from StringIO import StringIO
import whatap.util.file_util as file_util
from whatap.util.ip_util import IPUtil as ip_util
from whatap.io.data_outputx import DataOutputX
import whatap.util.process_util as process_util
import psutil

import multiprocessing



class ProcessPerfInfo:
    def __init__(self):
        self.ppid = None
        self.pid = None
        self.cpu = None
        self.memoryBytes = None
        self.memoryPercent = None
        self.readBps = 0.0
        self.writeBps = 0.0
        self.cmd1 = None
        self.cmd2 = None
        self.readIops = 0.0
        self.writeIops = 0.0
        self.user = None
        self.state = None
        self.createTime = None
        self.net = []
        self.file = []
        self.sharedMemory = 0

    def __str__(self):
        b = StringIO()
        b.write('ppid:')
        b.write(self.ppid)
        b.write('\npid')
        b.write(self.pid)
        b.write('\ncpu')
        b.write(self.cpu)
        b.write('\nmemory')
        b.write(self.memoryBytes)
        b.write('\nsharedMemory')
        b.write(self.sharedMemory)

        return b.getvalue()

class IpPort:
    def __init__(self, localip=0, localport=0, conn=0, ilocaladdr=0, inode=0):
        self.localip = localip
        self.localport = localport
        self.ilocaladdr = ilocaladdr
        self.iremoteaddr = 0
        self.conn = conn
        self.inode = inode

    def __str__(self):
        buf = StringIO()
        buf.write("localip=")
        buf.write(self.localip)
        buf.write("\nlocalport=")
        buf.write(self.localport)
        buf.write("\nilocaladdr=")
        buf.write(self.ilocaladdr)
        buf.write("\niremoteaddr=")
        buf.write(self.iremoteaddr)
        buf.write("\nconn=")
        buf.write(self.conn)
        buf.write("\ninode=")
        buf.write(self.inode)

        return buf.getvalue()


class FileInfo:
    def __init__(self, name=None, size=0):
        self.name = name
        self.size = size

def GetProc():
    procPerfs = getProcessPerfList()

    return procPerfs

class _ProcPerfCache:
    def __init__(self, cpu_times = None, proc_map = None):
        self.cpu_times = cpu_times
        self.proc_map = proc_map
        self.timestamp = time.time()

def parseNetwork(conns):
    pass


def parseOpenFile(files):
    flookup = {}
    fileusage =[]

    for f in files:
        if f.path and f.path.endswith('.log'):
            flookup[f.path] = 0
    for p in flookup.keys():
        filestat = os.stat(p)
        if filestat:
            fileusage.append(FileInfo(name=p, size=filestat.st_size))
    return fileusage

def calcPs(v, lastv, timediff):
    return float(v - lastv) / float(timediff)



proc_shm_cache = {}
oldProcPerfCache = None
cpuCore= psutil.cpu_count()

def getProcessPerfList():
    global proc_shm_cache
    proc_map = {}

    vmem = psutil.virtual_memory()
    totalMem = vmem.total
    pageSize = vmem.pagesize
    proc_perfs = []


    global oldProcPerfCache

    for proc in psutil.process_iter():
        with proc.oneshot():
            try:
                timestamp = time.time()
                iocounters = proc.io_counters()
                #cputimes = proc.cpu_times()
                proc_map[proc.pid] = (proc, iocounters, timestamp)

                if not oldProcPerfCache:
                    continue
                else:
                    if proc.pid == 2 or proc.ppid() == 2 or proc.pid not in oldProcPerfCache.proc_map:
                        continue


                    p = ProcessPerfInfo()
                    p.pid = proc.pid
                    p.ppid = proc.ppid()
                    p.user = proc.username()
                    p.memoryBytes = proc.memory_info().rss * pageSize
                    p.state = proc.status()

                    p.memoryPercent = 100.0 * p.memoryBytes / totalMem

                    p.cmd1 = proc.exe()
                    p.cmd2 = ' '.join(proc.cmdline())

                    p.createTime = int(proc.create_time())

                    _, old_iocounters, old_timestamp = oldProcPerfCache.proc_map[proc.pid]
                    timediff = timestamp - old_timestamp

                    p.cpu = proc.cpu_times().pcpu / cpuCore

                    #cpu_jiff_diff = timediff * cpuCore
                    #cpu_this_time = cputimes.user + cputimes.system 
                    #cpu_last_time = old_cputimes.user + old_cputimes.system
                    #p.cpu = float(100) * float(cpu_this_time - cpu_last_time) / cpu_jiff_diff
                    p.readBps = calcPs(iocounters.total_bytes, old_iocounters.total_bytes, timediff)
                    p.writeBps = float(0)
                    p.readIops = float(0)
                    p.writeIops = float(0)

                    p.net = []
                    #p.net = parseNetwork(proc.connections())
                    p.file = parseOpenFile(proc.open_files())

                    proc_perfs.append(p)

            except psutil.ZombieProcess, e:
                continue
            except psutil.NoSuchProcess, e:
                continue

    procPerfCache = _ProcPerfCache(proc_map=proc_map)
    oldProcPerfCache = procPerfCache
    return proc_perfs
 
def test():
    while True:
        procs = GetProc()
        print
        procs
        if not procs:
            time.sleep(5)
            continue
        time.sleep(5)


if __name__ == '__main__':
    test()
