# Needed for the FilesStuff class
import os
import numpy as np
# Needed for the TCPComm class
import socket

class TCPComm:
    
    __HEADER = "JRO"
    __TYPE = "ABS"
    
    def __init__(self, ipSource, iDSource, ipDestino, iDDestino, portDestino, asServer=False):
        
        self.ipSource = ipSource
        self.iDSource = iDSource 
        self.ipDestino = ipDestino
        self.iDDestino = iDDestino
        self.portDestino = portDestino
        self.addr = (ipDestino,portDestino)
        
        self.sc = "none"
        self.answer = "none"     #test
        self.asServer = False
        self.len = "000000"
        self.crc = "0"
        
        self.openSocket(asServer)
    
    def openSocket(self, asServer):
        
        #self.socket_c = socket.socket(AF_INET,SOCK_DGRAM)
#        self.socket_c = socket.socket()
#        self.socket_c.connect((self.ipDestino, self.portDestino))
        
        if asServer:
            self.socket_c = socket.socket()
#            self.configAsServer()
            self.socket_c.bind(self.addr)
            self.asServer = True
        else:
#            self.configAsClient()
            self.asServer = False        #Socket is opened at the sendData function
    
#    def configAsClient(self):
        #Buscar broadcast TCP
#        self.socket_c.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
#         self.socket_c.connect(self.addr)
#         pass
        
#    def configAsServer(self):
#        
#        self.socket_c.bind(self.addr)
        
    def waitData(self):
        if self.asServer == True:
            trama_rx, l = self.waitAsServer()
        else:
            trama_rx, l = self.waitAsClient()
        
        ipSource, ipDestino, cmd, data = self.__getTrama(trama_rx, l)
        
        return ipSource, ipDestino, cmd, data

    def waitAsClient2(self, nbytes = 1024):
        print "\nWaiting the server."    
            # Short data through ethernet
        trama_rx = self.socket_c.recv(nbytes)
        print "\nThis socket has received this data: " + str(trama_rx)
        
        return trama_rx
     
    def waitAsServer2(self, nbytes = 1024):
        print "\nWaiting some client."
        self.socket_c.listen(1)
        sc, addr = self.socket_c.accept()
        self.sc = sc
        self.answer = addr
        # Big data through ethernet
        trama_rx = ""
        while True:
            tmp = self.sc.recv(nbytes)
            trama_rx = trama_rx + tmp
            if trama_rx[-4:] == "quit":
                break 

        print "\nThis socket has received some data from: " + str(self.answer)
        
        return trama_rx 
    
    def waitAsServer(self, nbytes = 1024):
        print "\nWaiting some client."
        self.socket_c.listen(1)
        sc, addr = self.socket_c.accept()
        self.sc = sc
        self.answer = addr
        # Big data through ethernet
        cnt = 0;
        first = 0;
        trama_rx = ""
        while True:
            tmp = self.sc.recv(nbytes)
            trama_rx = trama_rx + tmp
            cnt = len(trama_rx)
            if first == 0:
                first = 1
                lng = int(trama_rx[20:26])
                frm_lng= lng + 31               # 31 bytes are fixed and added to the data size to get the frame size
            if cnt == frm_lng:
                break 

        print "\nThis socket has received some data from: " + str(self.answer)
        
        return trama_rx, lng
        
    def waitAsClient(self, nbytes = 1024):
        print "\nWaiting the server."    
            # Short data through ethernet
        try:
            trama_rx = self.socket_c.recv(nbytes)
            lng = int(trama_rx[20:26])
        except:
            print "Waiting error"
            trama_rx = "Error"
            lng = 0
        else:
            print "\nThis socket has received this data: " + str(trama_rx)
            
        return trama_rx, lng
        
    def sendData2(self, cmd, data, ipDestino):

        trama_tx = self.__HEADER + ":" + self.__TYPE + ":" + str(self.ipSource) + ":" + str(ipDestino) + \
        ":" + str(self.len) + ":" + str(cmd) + ":" + str(data) + ":" + str(self.crc) + ":" + "quit"
        
        if self.asServer == True:
            self.SendAsServer(trama_tx)
        else:
            self.SendAsClient(ipDestino, trama_tx)

    def sendData(self, cmd, data, ipDestino):

        trama_tx = self.__HEADER + self.__TYPE + self.iDSource + \
        self.iDDestino + self.len + str(cmd) + str(data) + self.crc
        
        self.len = self.int2str(len(data))
        
        trama_tx = self.__HEADER + self.__TYPE + self.iDSource + \
        self.iDDestino + self.len + str(cmd) + str(data) + self.crc
        
        if self.asServer == True:
            self.SendAsServer(trama_tx)
        else:
            self.SendAsClient(ipDestino, trama_tx)
        
    def SendAsServer(self, trama_tx):
        
        self.sc.send(trama_tx)
        print "Sending message:[" + trama_tx + "] to: " + str(self.answer)        
        
    
    def SendAsClient(self, ipDestino, trama_tx):
        
        try:
            self.socket_c.connect((ipDestino, self.portDestino))
        except:
            print "Connection error with:" + ipDestino
        else:      
            self.socket_c.send(trama_tx)
            print "Sending message:[" + trama_tx + "] to: " + ipDestino
    
    def __getTrama2(self, trama):
        
        FrameList = trama.split(':')

        header = FrameList[0]
        TypeOfInstrument = FrameList[1]
        ipSource = FrameList[2]
        ipDestino = FrameList[3]
        len = FrameList[4]
        cmd = FrameList[5]
        data = FrameList[6]
        crc = FrameList[7]
        trash = FrameList[8]
        
        return ipSource, ipDestino, cmd, data

    def __getTrama(self, trama, l):
        
        header = trama[0:3]
        TypeOfInstrument = trama[3:6]
        ipSource = trama[6:13]
        ipDestino = trama[13:20]
        len = trama[20:26]
        cmd = trama[26:30]
        data = trama[30:30+int(l)]
        crc = trama[30+ int(l):]
        
        return ipSource, ipDestino, cmd, data
    
    def close_socket(self):
        self.socket_c.close()

    def open_socket(self):
        self.socket_c = socket.socket()
    
    def int2str(self, n):
        
        str_n = str(n)
        l_n = len(str_n)
        if l_n == 1:
            str_n = "00000" + str_n
        elif l_n == 2:
            str_n = "0000" + str_n
        elif l_n == 3:
            str_n = "000" + str_n
        elif l_n == 4:
            str_n = "00" + str_n            
        elif l_n == 5:
            str_n = "0" + str_n
        return  str_n

class   FilesStuff():
        
    def lst2string(self, lst):
        string=''
        for i in lst:
            string=string+i
        return string

    def string2lst(self, string):
        lst = []
        for i in string:
            lst.append(i)
        return lst
    
    
    def file1(self, filename, type):
        lst = self.string2lst(filename)
        fin = -1
        t = len(lst)
        for i in np.arange(-1,-t,-1):
            if lst[i]=='/':
                fin=i
                break   
        if type == '1':
            nombre2 = lst[fin+1:]
            nombre2[-1]='s'
            nombre2 = self.lst2string(nombre2)
            return nombre2
        if type == '2':
            nombre2 = lst[fin+1:]
            nombre2[-1]='1'
            nombre2 = self.lst2string(nombre2)
            return nombre2
    
    
    def EliminaSaltoDeLinea(self,cadena):
        i = 0
        for elemento in cadena:
            if elemento =='\n' or elemento =='\r':
                pass
            else:
                i=i+1
        return cadena [:i]

    def NumeroDeExperimentos(self, path):
        fichero1=open(path,'r')
        cont=0
        for cadena in fichero1:
            cont=cont+1
            if cont==3:
                nexp=''
                pos=0
                for elemento in cadena:
                    pos=pos+1
                    if elemento=='=':
                        nexp=int(cadena[pos:])
                        return nexp
        fichero1.close()
    
    def Paridad(self, numero):
        if numero%2==0: return 'par'
        elif numero%2==1: return 'impar'
        
    def EvaluaCadena(self,cadena):
        if len(cadena)>35:
            if cadena[-1]=='$':
                return cadena[-35:-2]
            elif cadena[-1]==']':
                return cadena[-34:-1]
        else:
            return None

    def GuardaEnLista(self,path):
        fichero=open(path,'r')
        lista=[]
        for cadena in fichero:
            cadena = self.EliminaSaltoDeLinea(cadena)
            cadena = self.EvaluaCadena(cadena)
            if cadena != None:
                lista.append(cadena)
        fichero.close()
        return lista
    
    def CreaFicherosPrevios(self, path, archivo):
        vector = self.GuardaEnLista(archivo)
        for i in range(1,self.NumeroDeExperimentos(archivo)+1):
            fichero =open(path + str(i)+ '.txt','w')
            for j in range(0,16):
                fichero.write(vector[j+16*(i-1)]+'\n')
            fichero.close()
    
    def CapturaValoresEnArchivo(self, path, polarizacion='up'):
        fichero =open(path,'r')
        cnt=0
        lstup=[]
        lstdw=[]
        for cadena in fichero:
            cnt=cnt+1
            if cnt==1:
                nu01=cadena[1:4]
                nu02=cadena[5:8]
                nu03=cadena[9:12]
                nu04=cadena[13:16] 
                eu01=cadena[17:20]
                eu02=cadena[21:24]
                eu03=cadena[25:28]
                eu04=cadena[29:32]
            if cnt==2:
                nu05=cadena[1:4]
                nu06=cadena[5:8]
                nu07=cadena[9:12]
                nu08=cadena[13:16] 
                eu05=cadena[17:20]
                eu06=cadena[21:24]
                eu07=cadena[25:28]
                eu08=cadena[29:32]
            if cnt==3:
                nu09=cadena[1:4]
                nu10=cadena[5:8]
                nu11=cadena[9:12]
                nu12=cadena[13:16] 
                eu09=cadena[17:20]
                eu10=cadena[21:24]
                eu11=cadena[25:28]
                eu12=cadena[29:32]
            if cnt==4:
                nu13=cadena[1:4]
                nu14=cadena[5:8]
                nu15=cadena[9:12]
                nu16=cadena[13:16] 
                eu13=cadena[17:20]
                eu14=cadena[21:24]
                eu15=cadena[25:28]
                eu16=cadena[29:32]
            if cnt==5:
                wu01=cadena[1:4]
                wu02=cadena[5:8]
                wu03=cadena[9:12]
                wu04=cadena[13:16] 
                su01=cadena[17:20]
                su02=cadena[21:24]
                su03=cadena[25:28]
                su04=cadena[29:32]
            if cnt==6:
                wu05=cadena[1:4]
                wu06=cadena[5:8]
                wu07=cadena[9:12]
                wu08=cadena[13:16] 
                su05=cadena[17:20]
                su06=cadena[21:24]
                su07=cadena[25:28]
                su08=cadena[29:32]
            if cnt==7:
                wu09=cadena[1:4]
                wu10=cadena[5:8]
                wu11=cadena[9:12]
                wu12=cadena[13:16] 
                su09=cadena[17:20]
                su10=cadena[21:24]
                su11=cadena[25:28]
                su12=cadena[29:32]
            if cnt==8:
                wu13=cadena[1:4]
                wu14=cadena[5:8]
                wu15=cadena[9:12]
                wu16=cadena[13:16] 
                su13=cadena[17:20]
                su14=cadena[21:24]
                su15=cadena[25:28]
                su16=cadena[29:32]
            if cnt==9:
                nd01=cadena[1:4]
                nd02=cadena[5:8]
                nd03=cadena[9:12]
                nd04=cadena[13:16] 
                ed01=cadena[17:20]
                ed02=cadena[21:24]
                ed03=cadena[25:28]
                ed04=cadena[29:32]
            if cnt==10:
                nd05=cadena[1:4]
                nd06=cadena[5:8]
                nd07=cadena[9:12]
                nd08=cadena[13:16]                    
                ed05=cadena[17:20]
                ed06=cadena[21:24]
                ed07=cadena[25:28]
                ed08=cadena[29:32]
            if cnt==11: 
                nd09=cadena[1:4]
                nd10=cadena[5:8]
                nd11=cadena[9:12]
                nd12=cadena[13:16]                    
                ed09=cadena[17:20]
                ed10=cadena[21:24]
                ed11=cadena[25:28]
                ed12=cadena[29:32]
            if cnt==12: 
                nd13=cadena[1:4]
                nd14=cadena[5:8]
                nd15=cadena[9:12]
                nd16=cadena[13:16]
                ed13=cadena[17:20]
                ed14=cadena[21:24]
                ed15=cadena[25:28]
                ed16=cadena[29:32]                
            if cnt==13:
                wd01=cadena[1:4]
                wd02=cadena[5:8]
                wd03=cadena[9:12]
                wd04=cadena[13:16] 
                sd01=cadena[17:20]
                sd02=cadena[21:24]
                sd03=cadena[25:28]
                sd04=cadena[29:32]
            if cnt==14:
                wd05=cadena[1:4]
                wd06=cadena[5:8]
                wd07=cadena[9:12]
                wd08=cadena[13:16]                    
                sd05=cadena[17:20]
                sd06=cadena[21:24]
                sd07=cadena[25:28]
                sd08=cadena[29:32]
            if cnt==15: 
                wd09=cadena[1:4]
                wd10=cadena[5:8]
                wd11=cadena[9:12]
                wd12=cadena[13:16]                    
                sd09=cadena[17:20]
                sd10=cadena[21:24]
                sd11=cadena[25:28]
                sd12=cadena[29:32]
            if cnt==16: 
                wd13=cadena[1:4]
                wd14=cadena[5:8]
                wd15=cadena[9:12]
                wd16=cadena[13:16]
                sd13=cadena[17:20]
                sd14=cadena[21:24]
                sd15=cadena[25:28]
                sd16=cadena[29:32]
        blck_1_up = [nu01,nu02,nu03,nu04,eu01,eu02,eu03,eu04,nu05,nu06,nu07,nu08,eu05,eu06,eu07,eu08]
        blck_1_dw = [nd01,nd02,nd03,nd04,ed01,ed02,ed03,ed04,nd05,nd06,nd07,nd08,ed05,ed06,ed07,ed08]
        blck_2_up = [nu09,nu10,nu11,nu12,eu09,eu10,eu11,eu12,nu13,nu14,nu15,nu16,eu13,eu14,eu15,eu16]
        blck_2_dw = [nd09,nd10,nd11,nd12,ed09,ed10,ed11,ed12,nd13,nd14,nd15,nd16,ed13,ed14,ed15,ed16]
        blck_3_up = [wu01,wu02,wu03,wu04,su01,su02,su03,su04,wu05,wu06,wu07,wu08,su05,su06,su07,su08]
        blck_3_dw = [wd01,wd02,wd03,wd04,sd01,sd02,sd03,sd04,wd05,wd06,wd07,wd08,sd05,sd06,sd07,sd08]
        blck_4_up = [wu09,wu10,wu11,wu12,su09,su10,su11,su12,wu13,wu14,wu15,wu16,su13,su14,su15,su16]
        blck_4_dw = [wd09,wd10,wd11,wd12,sd09,sd10,sd11,sd12,wd13,wd14,wd15,wd16,sd13,sd14,sd15,sd16]
        
        lstup = blck_1_up + blck_2_up + blck_3_up + blck_4_up
        lstdw = blck_1_dw + blck_2_dw + blck_3_dw + blck_4_dw
        
        if polarizacion=='up': 
            return lstup
        elif polarizacion=='dw':
            return lstdw
        fichero.close()
        
    def CreaFormatoFinal(self, path, filename):
        ne=self.NumeroDeExperimentos(filename)
        
        #nombre01 = file1(archivo,'1')
        nombre02 = self.file1(filename,'2')
        fichero=open(path + 'CentralControlFormat.txt','w')
        fichero.write(nombre02+'\n')        
        fichero.write(str(ne)+'\n')

        for i in range(1,65):
            
            if i<10:
                nmod = '0'+str(i)
            else: nmod = str(i)
            
            fichero.write("ABS_" + nmod+'\n')
            
            for j in range(1,ne+1):
                ruta=path+str(j)+'.txt'
                lu=self.CapturaValoresEnArchivo(ruta,polarizacion='up')
                ld=self.CapturaValoresEnArchivo(ruta,polarizacion='dw')
                part1=''
                part2=''
                if lu[i-1]=='1.0': part1='000'
                if lu[i-1]=='2.0': part1='001'
                if lu[i-1]=='3.0': part1='010'
                if lu[i-1]=='0.0': part1='011'
                if lu[i-1]=='0.5': part1='100'
                if lu[i-1]=='1.5': part1='101'
                if lu[i-1]=='2.5': part1='110'
                if lu[i-1]=='3.5': part1='111'
                if ld[i-1]=='1.0': part2='000'
                if ld[i-1]=='2.0': part2='001'
                if ld[i-1]=='3.0': part2='010'
                if ld[i-1]=='0.0': part2='011'
                if ld[i-1]=='0.5': part2='100'
                if ld[i-1]=='1.5': part2='101'
                if ld[i-1]=='2.5': part2='110'
                if ld[i-1]=='3.5': part2='111'
                fichero.write(part1+part2+'\n')
            fichero.write('------'+'\n')
        fichero.close()
    
    def EliminaArchivosEnLaCarpeta(self, path, filename):
        ne=self.NumeroDeExperimentos(filename)   
        for i in range(1,ne+1):
            os.remove(path + str(i)+'.txt')
                

    def toCentralControlFormat(self, filename):
        """ Funcion que genera un archivo para el control central"""
    
        path = os.getcwd() + '/'               
        self.CreaFicherosPrevios(path, filename)
        self.CreaFormatoFinal(path, filename)
        self.EliminaArchivosEnLaCarpeta(path, filename)
