import socket
import sys
import os
import subprocess
import threading
import time

class MeasureClientThread(threading.Thread):
    def run(self):
        """When called, given an object, executes its runServer method.
        Could be modified to run other methods as well"""
        self.object.runMeasure()
    def __init__(self, threadId,object):
        threading.Thread.__init__(self)
        self.object = object
        self.threadId = threadId

class ServerThread(threading.Thread):
    def run(self):
        """When called, given an object, executes its runServer method.
        Could be modified to run other methods as well"""
        self.object.runServer()
    def __init__(self, threadId,object):
        threading.Thread.__init__(self)
        self.object = object
        self.threadId = threadId

class MeasureClient:
	def __init__(self,host,port,nicList,experimentTime,resultName="testando",pathServerDaemon="/lab/users/LuisH/souza/horizon/cpuAllocation/xenprototype/CpuAllocation/measureThroughputServer.py"):

		self.host = host
		self.port = port
		self.experimentTime = experimentTime
		self.resultName = resultName
		#Start server daemon
		self.pathServerDaemon = pathServerDaemon
		ServerThread("2",self).start()
		self.nicList = nicList
		self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.connectionStatus = False
		#Wait server to start
		while (self.connectionStatus == False):	
			try:
				self.s.connect((self.host, self.port))
				self.connectionStatus = True
			except:
				connectionStatus = False
		self.s.send(str(self.nicList))
		self.setMeasureCollectedStatus(True)
		self.setExperimentStatus(True)
		self.finalResult = ""
		self.sampleNumber = 1

	def setMeasureCollectedStatus(self,status):
		self.measureCollectedStatus = status

	def getMeasureCollectedStatus(self):
		return self.measureCollectedStatus

	def setExperimentStatus(self,status):
		self.experimentStatus = status

	def getExperimentStatus(self):
		return self.experimentStatus

	def setLastMeasure(self,measure):
		self.lastMeasure = measure
		self.setMeasureCollectedStatus(False)
		
	def getLastMeasure(self):
		#Collect the new measurment in the lastMeasure attribute and set True to measureCollectedStatus, indicating that the measure has been collected.If the measure is not new this method returns -1
		if self.getMeasureCollectedStatus() == True :
			return -1
		self.setMeasureCollectedStatus(True)
		return self.lastMeasure

	def __addMeasureResult(self,line):
		#Add a measure to the final result
		self.finalResult = self.finalResult + line + "\n"

	def writeResultFile(self):
		#Write the result file specified by self.resultName
		resultFile = open(self.resultName,'w')
		resultFile.write(self.finalResult)
		resultFile.close()


	#Run the Measure Server. It should be executed by a thread
	def runServer(self):
		cmd = "ssh root@" + str(self.host) + " \" " + str(self.pathServerDaemon) + " " + str(self.port) + " \" "
		self.server = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

	#Run the Measure gatherer. It should be executed by a thread
	def runMeasure(self):
		#Gather current time
		initialTime = time.time()
		endTime = int(initialTime) + self.experimentTime
		while (int(time.time()) <= endTime) :
			data = self.s.recv(1024)
			#Create a list of all unreceived measures
			listMeasure = data.split(":")
			#Use only the last measure
			measure = listMeasure[len(listMeasure)-2]
			self.setLastMeasure(measure)
			#Write the measure to resultLine
			resultLine = str(float(self.sampleNumber)) + " " + str(float(self.lastMeasure)/float(1000))
			self.__addMeasureResult(resultLine)
			self.sampleNumber = self.sampleNumber + 1
		self.s.close()
		self.server.kill()
		#Write to result file
		self.writeResultFile()
		self.setExperimentStatus(False)
