import os
import library3
import time
from threading import Thread
import threading
import Queue

class ABSServer:
    
    def __init__(self,ipSource="localhost", ipDestino="192.168.1.117", portDestino=7000, ipDestino2="192.168.1.11", portDestino2=5500, rx_buffer = "default"):
    
        self.ipSource = ipSource
        self.ipDestino = ipDestino
        self.portDestino = portDestino
        
        self.ipDestino2 = ipDestino2
        self.portDestino2 = portDestino2
        
        self.tx_buffer = "default"
#        self.rx_buffer = "default"
        self.rx_buffer = rx_buffer 
        self.enaModules = []
        self.bits = []
        self.phase = []
        self.txFile = []
        self.rxFile = []
        
        self.createObjects()
        
        print "Checking control modules, please wait ..."
        self.enaModules = self.checkAntenna()
#        self.enaModules = [1,12]
        print "Starting automatic control module status."
        self.__StartingAutomaticControlModules()
        self.__AutomaticControlModules()
        
    def createObjects(self):
        
        asServer = True
        self.commServerObj = library3.TCPComm("Central_Control", "CeCnMod", self.ipDestino, "CnMod01", self.portDestino, asServer)
        self.commClientObj = library3.TCPComm("Central_Control", "CeCnMod", self.ipDestino2, "CnMod01", self.portDestino2)
        self.wFiles = library3.FilesStuff()
            
    def waitRequest(self):
        
        #Using rx buffer
#        ipSource, ipDestino, cmd, self.rx_buffer = self.commServerObj.waitData()
        ipSource, ipDestino, cmd, rx_buffer = self.commServerObj.waitData()
        
        if cmd == "SNDF":
            datarpta = self.__sendFile2Modules(cmd = cmd, rx_buffer = rx_buffer)

        if cmd == "GETF":
            datarpta = self.__getFileFromModules(cmd = cmd, rx_buffer = rx_buffer)
                    
        if cmd == "CHGB":
            datarpta = self.__changeBeam(cmd = cmd, rx_buffer = rx_buffer)
        
        if cmd == "ANST":
            datarpta = self.__getControlModuleStatus(cmd = cmd, rx_buffer = rx_buffer)

        if cmd == "BGPH":
            datarpta = self.__getControlModuleBigPhase(cmd = cmd, rx_buffer = rx_buffer)

        if cmd == "LWPH":
            datarpta = self.__getControlModuleLowPhase(cmd = cmd, rx_buffer = rx_buffer)
                        
        if cmd == "NTST":
            datarpta = self.__getConnectionStatus(cmd = cmd, rx_buffer = rx_buffer)
        
        self.commServerObj.sendData(cmd=cmd, data=datarpta, ipDestino = ipSource)

    def __checkModule(self, address):
        
        cmd = "ping -c 1 -w 1 192.168.1."+ str(address) + " >> /dev/null"
        status = os.system(cmd)
        
        if status == 256:
            return False
        
        return True

    def __writeReport(self, enaModules):
        
        status_array = ["Status of modules\n"]
        status_array.append("----------------\n")
        
        for address in range(1,65):
            if address in enaModules:
                status_array.append("192.168.1." + str(address) + " [1 1]\n")
            else:    
                status_array.append("192.168.1." + str(address) + " [0 0]\n")
        
        filename = "module_status.txt"
        self.__writeFile(filename,status_array)
#        f = open("module_status.txt","w")
#        f.writelines(status_array)
#        f.close()
    
    
    def __CreateFile(self, filename):

        fobj = open(filename,"w")
        fobj.close()
        
    def __writeNewFile(self, filename, data):

        fobj = open(filename,"w")
        fobj.writelines(data)
        fobj.close()

    def __writeFile(self, filename, data):

        fobj = open(filename,"a")
        fobj.writelines(data)
        fobj.close()
                
    def __checkAntenna(self):
        
        """
        Direccion de los modulos de las antenas:
        
            Norte    :    01-16
            Este     :    17-32
            Oeste:   :    33-48
            Sur      :    49-64
        
        """
        
        enaModules2 = []
        
        for address in range(1,65): 
            if self.checkModule(address):
                enaModules2.append(address)
        
        self.__writeReport(enaModules2)
        return  enaModules2
    
    def checkModule(self, arg, queue):
        cmd = "ping -c 1 -w 1 192.168.1."+ str(arg) + " >> /dev/null"
        status = os.system(cmd)
        if status == 256:
            result = "failed"
        else:
            result = "ok"
        queue.put({arg: result})

    def checkAntenna(self):

        iD = range(1,256)
        q = Queue.Queue()
        threads = []
        tOut = []
        modules = []
    
        for argument in iD:
            t = Thread(target=self.checkModule, args=(argument, q))
            t.start()
            threads.append(t)
    
        for t in threads:
            t.join()
    
        for _ in range(len(iD)):
            tOut.append(q.get())
    
        for i in tOut:
            if i.values()[0] == 'ok':
                modules.append(i.keys()[0])
    
        return modules
    
    def __ConnectionWithControlModules(self,data,cmd,id):

        self.commClientObj.open_socket()
        ip = "192.168.1." + str(id)
        self.commClientObj.sendData(cmd, data, ip)
        ipSource, ipDestino, cmd, tmp = self.commClientObj.waitData()
        self.commClientObj.close_socket()

        return tmp     

    def abs2ControlModuleFormatFile(self, filename):
        
        #From matriz to control module format
        self.wFiles.toCentralControlFormat(filename)
        FileName = "CentralControlFormat.txt"
        F_Obj = open(FileName,"r")
        FileList = F_Obj.readlines()
        F_Obj.close()
        FileStr = "".join(FileList)
        
        return FileStr

    def __All2Blocks(self,input):
        
        rx_frame_lst = input.split('\n',2)

        header = rx_frame_lst[0] + "\n"
        control_modules_str = rx_frame_lst[2]        
        control_modules_lst = control_modules_str.split("------\n")
        
        return  header, control_modules_lst 
        
    
    def __sendFile2Modules(self,cmd, rx_buffer):
        
#        rx_buffer_lst = self.rx_buffer.split('\n',1)
        rx_buffer_lst = rx_buffer.split('\n',1)
        #Getting the filename from the begining of data
        filename = rx_buffer_lst[0]
        tmp = rx_buffer_lst[1]
        self.__writeFile(filename,tmp)
        data = self.abs2ControlModuleFormatFile(filename)
        #Needed for the loop
        header, control_modules_lst = self.__All2Blocks(data)
        correct = 0
        
        for id in range(1,65):
            
            if id not in self.enaModules:
                continue
            
            if self.__ConnectionWithControlModules(header + control_modules_lst[id-1], cmd, id) == "OK":
                correct = correct + 1

        if correct == len(self.enaModules):
            rpta = "OK"
        else:
            rpta = "Failure"

        return rpta
    
    def __getFileFromModules(self, cmd, rx_buffer):

        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            file = self.__ConnectionWithControlModules(rx_buffer,cmd,id)
            del self.rxFile[id-1]
            self.rxFile.insert(id-1, file)            

    def __changeBeam(self, cmd, rx_buffer):
        
        correct = 0
#        enaModules = self.checkAntenna()
#        enaModules = [11,12,13,14]
        
        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            if self.__ConnectionWithControlModules(rx_buffer,cmd,id) == "OK":
                correct = correct + 1
                
        if correct == len(self.enaModules):
            rpta = "OK"
        else:
            rpta = "Failure"

        return rpta

    def __getControlModuleStatus(self, cmd, rx_buffer):

#        all_blocks = ""
#        all_blocks = []
#        enaModules = self.checkAntenna()
#        enaModules = [11,12,13,14]
        
        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            bits = self.__ConnectionWithControlModules(rx_buffer,cmd,id)
            del self.bits[id-1]
            self.bits.insert(id-1, bits)
        
#            all_blocks.append(one_block)
        #Using tx buffer
        
#        return all_blocks
        
    def __getControlModuleBigPhase(self, cmd, rx_buffer):

#        all_blocks = ""
        all_blocks = []
#        enaModules = self.checkAntenna()
#        enaModules = [11,12,13,14]
        
        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            one_block = self.__ConnectionWithControlModules(rx_buffer,cmd,id)
        
#            all_blocks = all_blocks + one_block
            all_blocks.append(one_block)
        #Using tx buffer
        return all_blocks

    def __getControlModuleLowPhase(self, cmd, rx_buffer):

#        all_blocks = ""
#        all_blocks = []
#        enaModules = self.checkAntenna()
#        enaModules = [11,12,13,14]
        
        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            phase = self.__ConnectionWithControlModules(rx_buffer,cmd,id)
            del self.phase[id-1]
            self.phase.insert(id-1, phase)
#            all_blocks = all_blocks + one_block
#            all_blocks.append(one_block)
        #Using tx buffer
#        return all_blocks
        
    def __getConnectionStatus(self, cmd, rx_buffer):
    
        ena = self.checkAntenna()
        print ena
        self.enaModules = ena

        blockLst = []
        
        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            blockStr = self.__ConnectionWithControlModules(rx_buffer,cmd,id)        
            blockLst.append(blockStr + ", 192.168.1." + str(id) + "\n") 
        #Using tx buffer
        all_blocks = "".join(blockLst)
        
        return all_blocks

    def getConnectionStatus(self, cmd):
    
        ena = self.checkAntenna()
        self.enaModules = ena

        blockLst = []
        
        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            blockStr = self.__ConnectionWithControlModules(self.rx_buffer,cmd,id)        
            blockLst.append(blockStr + ", 192.168.1." + str(id) + "\n") 
        #Using tx buffer
        self.tx_buffer = "".join(blockLst)
        print self.tx_buffer
        
        return  self.tx_buffer
    
    def getControlModuleStatus(self, cmd):

        all_blocks = ""
#        enaModules = self.checkAntenna()
#        enaModules = [11,12,13,14]
        
        for id in range(1,65):
            if id not in self.enaModules:
                continue
            
            one_block = self.__ConnectionWithControlModules(self.rx_buffer,cmd,id)
        
            all_blocks = all_blocks + one_block
        #Using tx buffer
        print all_blocks
        self.tx_buffer = all_blocks
        
        return all_blocks
    
    def __StartingAutomaticControlModules(self):
        
        #Starting file
        self.__CreateFile("Monitoring.txt")
#        data = "MOD.\t BITS\t\t   PHASE\n"
#        self.__writeFile("Monitoring.txt", data)
        #Starting lists
        self.txFile = list("------\n------\n------\n" for i in range(64))
        self.rxFile = list("------\n------\n------\n" for i in range(64))
        self.bits = list("------\n------\n------\n" for i in range(64))
        self.phase = list("----- -----\n----- -----\n----- -----\n" for i in range(64))
    
    def __AutomaticControlModules(self):
        
        cmd = "GETF"
        rx_buffer = "experimento1.ab1" + "\n"
        self.__getFileFromModules(cmd = cmd, rx_buffer = rx_buffer)
        
        print self.rxFile
        
        cmd = "ANST"
        rx_buffer = "1"
        self.__getControlModuleStatus(cmd = cmd, rx_buffer = rx_buffer)

        cmd = "LWPH"
        rx_buffer = "0"        
        self.__getControlModuleLowPhase(cmd = cmd, rx_buffer = rx_buffer)
        print  "Saving file..."
        
        
        print self.bits
        print self.phase
        
        self.__WritingMonitoringFile()

        threading.Timer(60, self.__AutomaticControlModules).start()
        
    def __WritingMonitoringFile(self):
        filename = "Monitoring.txt"
        data = '===============================' + '\n'
        self.__writeFile(filename, data)
        data = time.strftime('\t' + "%d%b%Y %I:%M:%S %p" + '\n', time.localtime())
        self.__writeFile(filename, data)
        data = "MOD.\t BITS\t\t   PHASE\n"
        self.__writeFile(filename, data)
        data = '===============================' + '\n'
        self.__writeFile(filename, data)
        for i in range(64):
            tmp = self.bits[i].split('\n',3)
            self.__writeFile(filename, ' ' + str(i + 1) + '\t\t' + tmp[2])
            tmp = self.phase[i].split('\n',3)
            self.__writeFile(filename, '\t\t' +  tmp[2] + '\n')
         
if __name__ == '__main__': 
    
    absObj = ABSServer()
    
    while 1:
        absObj.waitRequest()