import numpy as n
from xfab import tools,symmetry

class readhst:
    def __init__(self,direc,stem):
        self.direc = direc
        self.stem = stem
        self.open = False
        self.spot_id = None

    def _open(self,grainno,setno):
        filename = '%s/%s_gr%0.4d_set%0.4d.hst' \
            %(self.direc,self.stem,grainno,setno)
        try:
            self.hstfile = open(filename,'r')
        except:
            raise IOError, 'Cannot open this file'
        if self.hstfile > -1:
            self.open = True
        self.read_header()

    def read_header(self):
        par_name = self.hstfile.readline().split()[1:]
        par_val = self.hstfile.readline().split()
        self.par = {}
        for i in range(len(par_name)):
            self.par[par_name[i]] = int(par_val[i])
        
    def _close(self):
        self.hstfile.close()
        self.open = False

    def get_file_pos(self):
        if not self.open:
            print 'not open'
            try:
                self._open(grainno,setno)
            except:
                raise IOError, 'Cannot open hst file'
        self.hstfile.seek(0)
        fileeof = False
        self.filepos = []
        self.refpos = {}
        self.spotpos = {}
        while not fileeof:
            tmp_pos = self.hstfile.tell()
            dump = self.hstfile.readline()
            if dump[0:7] == 'REFL_ID':
                self.filepos.append(tmp_pos)
                (code, val) = dump.split('=')
                self.refpos[int(val)] = tmp_pos
                dump = self.hstfile.readline()
                if dump[0:7] == 'SPOT_ID':
                    (code, val) = dump.split('=')
                    self.spotpos[int(val)] = tmp_pos
            if dump == '':
                fileeof = True
        self.hstfile.seek(0)


    def read(self,grainno = None, setno = None, file_pos = None):
        if not self.open:
            print 'not open'
            try:
                self._open(grainno,setno)
            except:
                raise IOError, 'Cannot open hst file'
        if file_pos != None:
            self.hstfile.seek(file_pos)
        # READ REFL_ID
        refline = self.hstfile.readline()
        try:
            (code, val) = refline.split('=')
            if 'REFL_ID' in code:
                self.refl_id = int(val)
            else:
                raise IOError, 'REFL_ID not in line'
        except:
            raise IOError, 'Supposed REFL_ID line could not be split'
        # READ SPOT_ID
        refline = self.hstfile.readline()
        try:
            (code, val) = refline.split('=')
            if 'SPOT_ID' in code:
                self.spot_id = int(val)
            else:
                raise IOError, 'SPOT_ID not in line'
        except:
            raise IOError, 'Supposed SPOT_ID line could not be split'
        # Read shoebox
        box = self.hstfile.readline()
        oneD_shoebox = n.fromstring(box,sep=' ')
        elements = self.par['sbox_omega']*self.par['sbox_y']*self.par['sbox_z']
        self.shoebox = oneD_shoebox[:elements].reshape(self.par['sbox_omega'],self.par['sbox_y'],self.par['sbox_z'])


class readref:
    def __init__(self,direc,stem):
        self.direc = direc
        self.stem = stem
        self.open = False

    def _open(self,grainno,setno=0):
        filename = '%s/%s_gr%0.4d_set%0.4d.ref' \
            %(self.direc,self.stem,grainno,setno)
        print filename
        try:
            self.file = open(filename,'r')
        except:
            raise IOError, 'Cannot open this file'
        if self.file > -1:
            self.open = True

    def read(self,grainno = None, setno = None):
        if not self.open:
            try:
                self._open(grainno)
            except:
                raise IOError, 'Cannot open .ref file'
        line = self.file.readline()
        par = line.split()[1:] # order of refinfo 
        dump = self.file.readlines()
        self.colinfo = {}
        for i in range(0,len(par)):
            self.colinfo[par[i]] = i
            
        refinfo = []
        for i in range(len(dump)):
             refinfo.append(n.fromstring(dump[i],sep=' ').tolist())
        self.refinfo =  n.array(refinfo)

        

class readlog:
    def __init__(self,filename):
    
        self.nrefl = []
        self.rod = []
        self.id = []
        self.pos = []
        self.U = []
        self.UBI = []
        self.ia = []
        self.filename = filename

    def open(self):
        try:
            f=open(self.filename,'r')
        except IOError:
            logging.error('log_file: no file named %s' %self.filename)
            raise IOError
        
        input = f.readlines()
        f.close()

        self.no_grains = int(input[0].split()[1])
        nn = 23 # jumping to first grain

        for gr in range(self.no_grains):
            nn = nn + 1 # skip empty line
            nrefl = int(input[nn].split()[1])
            nn = nn + 1 # skip empty line
            # read grain positions from new grainspotter output

            if len(input[nn].split()) >= 4: 
                self.ia.append(eval(input[nn].split()[0]))
                self.pos.append(n.array([eval(input[nn].split()[1]),
                                         eval(input[nn].split()[2]),
                                         eval(input[nn].split()[3])]))

            nn = nn + 1 # skip empty line

            self.U.append(n.array([[eval(input[nn].split()[0]),
                                    eval(input[nn].split()[1]),
                                    eval(input[nn].split()[2])],
                                   [eval(input[nn+1].split()[0]),
                                    eval(input[nn+1].split()[1]),
                                    eval(input[nn+1].split()[2])],
                                   [eval(input[nn+2].split()[0]),
                                    eval(input[nn+2].split()[1]),
                                    eval(input[nn+2].split()[2])]]))

            nn = nn + 4 # jump to UBI

            self.UBI.append(n.array([[eval(input[nn].split()[0]),
                                      eval(input[nn].split()[1]),
                                      eval(input[nn].split()[2])],
                                     [eval(input[nn+1].split()[0]),
                                      eval(input[nn+1].split()[1]),
                                      eval(input[nn+1].split()[2])],
                                     [eval(input[nn+2].split()[0]),
                                      eval(input[nn+2].split()[1]),
                                      eval(input[nn+2].split()[2])]]))
            nn = nn + 4 # jump to Rod vector

            self.rod.append(n.array([eval(input[nn].split()[0]),
                                     eval(input[nn].split()[1]),
                                     eval(input[nn].split()[2])]))
            nn = nn + 5 # skip euler angles and quarternions

            nn = nn + 2 + nrefl # skip reflections

    def write_gff(self,gff_filename):

        f = open(gff_filename,'w')
        format = "%d "*1 + "%f "*7 + "%0.12f "*18 +"\n"
        out = "# grain_id mean_IA " +\
            "x y z rodx rody rodz " +\
            "U11 U12 U13 U21 U22 U23 U31 U32 U33" +\
            "UBI11 UBI12 UBI13 UBI21 UBI22 UBI23 UBI31 UBI32 UBI33 \n" 
        f.write(out)
        for i in range(self.no_grains):
            out = format %(i+1,
                           self.ia[i],
                           self.pos[i][0],
                           self.pos[i][1],
                           self.pos[i][2],
                           self.rod[i][0],
                           self.rod[i][1],
                           self.rod[i][2],
                           self.U[i][0,0],
                           self.U[i][0,1],
                           self.U[i][0,2],
                           self.U[i][1,0],
                           self.U[i][1,1],
                           self.U[i][1,2],
                           self.U[i][2,0],
                           self.U[i][2,1],
                           self.U[i][2,2],
                           self.UBI[i][0,0],
                           self.UBI[i][0,1],
                           self.UBI[i][0,2],
                           self.UBI[i][1,0],
                           self.UBI[i][1,1],
                           self.UBI[i][1,2],
                           self.UBI[i][2,0],
                           self.UBI[i][2,1],
                           self.UBI[i][2,2]
                           )
            f.write(out)
        f.close()   


#       from ImageD11 import columnfile
#         c = columnfile.columnfile(filename=None, new=True)
        
#         U11 =[]
#         U12 = U13 = []
#         U21 = U22 = U23 = []
#         U31 = U32 = U33 = []

#         for i in range(c.nrows):
#             U11.append(self.U[i][0,0])
#             U12.append(self.U[i][0,1])
#             U13.append(self.U[i][0,2])
#             U21.append(self.U[i][1,0])
#             U22.append(self.U[i][1,1])
#             U23.append(self.U[i][1,2])
#             U31.append(self.U[i][2,0])
#             U32.append(self.U[i][2,1])
#             U33.append(self.U[i][2,2])
#         print len(U11)
#         print U11
#         print c.nrows
#         c.addcolumn(U11,'U11')
#        c.addcolumn(U12,'U12')
#        c.addcolumn(U13,'U13')
#        c.addcolumn(U21,'U21')
#        c.addcolumn(U22,'U22')
#        c.addcolumn(U23,'U23')
#        c.addcolumn(U31,'U31')
#        c.addcolumn(U32,'U32')
#        c.addcolumn(U33,'U33')


class readuvm:
    def __init__(self,direc,stem):
        self.direc = direc
        self.stem = stem
        self.open = False
        self.spot_id = None

    def _open(self,grainno,setno):
        filename = '%s/%s_gr%0.4d_set%0.4d.uvm' \
            %(self.direc,self.stem,grainno,setno)
        try:
            self.file = open(filename,'r')
        except:
            raise IOError, 'Cannot open this file'
        if self.file > -1:
            self.open = True
        self.read_header()

    def read_header(self):
        par_name = self.file.readline().split()[1:]
        par_val = self.file.readline().split()
        self.par = {}
        for i in range(len(par_name)):
            self.par[par_name[i]] = int(par_val[i])
        
    def _close(self):
        self.file.close()
        self.open = False

    def get_file_pos(self,grainno,setno):
        if not self.open:
            print 'not open'
            try:
                self._open(grainno,setno)
            except:
                raise IOError, 'Cannot open uvm file'
        self.file.seek(0)
        fileeof = False
        self.filepos = []
        self.refpos = {}
        self.spotpos = {}
        while not fileeof:
            tmp_pos = self.file.tell()
            dump = self.file.readline()
            if dump[0:7] == 'REFL_ID':
                self.filepos.append(tmp_pos)
                (code, val) = dump.split('=')
                self.refpos[int(val)] = tmp_pos
                dump = self.file.readline()
                if dump[0:7] == 'SPOT_ID':
                    (code, val) = dump.split('=')
                    self.spotpos[int(val)] = tmp_pos
            if dump == '':
                fileeof = True
        self.file.seek(0)


    def read(self,grainno = None, setno = None, file_pos = None, refid= None, spotid = None):
        if not self.open:
            print 'not open'
            try:
                self._open(grainno,setno)
            except:
                raise IOError, 'Cannot open uvm file'
        if file_pos != None:
            self.file.seek(file_pos)
        if refid != None:
            self.file.seek(self.refpos[refid])
        if spotid != None:
            self.file.seek(self.spotpos[spotid])
        # READ REFL_ID
        refline = self.file.readline()
        try:
            (code, val) = refline.split('=')
            if 'REFL_ID' in code:
                self.refl_id = int(val)
            else:
                raise IOError, 'REFL_ID not in line'
        except:
            raise IOError, 'Supposed REFL_ID line could not be split'
        # READ SPOT_ID
        refline = self.file.readline()
        try:
            (code, val) = refline.split('=')
            if 'SPOT_ID' in code:
                self.spot_id = int(val)
            else:
                raise IOError, 'SPOT_ID not in line'
        except:
            raise IOError, 'Supposed SPOT_ID line could not be split'
        # Read shoebox
        uvm = self.file.readline()
        uvm = n.fromstring(uvm,sep=' ')
        elements = self.par['u_range']*self.par['v_range']
        self.uvm = uvm[:elements].reshape(self.par['u_range'],self.par['v_range'])

    def readall(self,grainno = None, setno = None):
        """
        read all uv-maps from from file and store
        in self.uvm
        from the variables self.refl_id and self.spot_id 
        refl_id and spot_id for the reflection can be found
        """
        if not self.open:
            print 'not open'
            try:
                self._open(grainno,setno)
            except:
                raise IOError, 'Cannot open uvm file'
        elements = self.par['u_range']*self.par['v_range']
        self.refl_id = []
        self.spot_id = []
        self.uvm = n.empty((1,self.par['u_range'],self.par['v_range']))
        # READ REFL_ID
        fileeof = False
        while not fileeof:
            refline = self.file.readline()
            try:
                (code, val) = refline.split('=')
                if 'REFL_ID' in code:
                    self.refl_id.append(int(val))
                else:
                    raise IOError, 'REFL_ID not in line'
            except:
                if refline == '':
                    fileeof = True
                    self.uvm = self.uvm[1:]
                    break
                else:
                    raise IOError, 'Supposed REFL_ID line could not be split'
            # READ SPOT_ID
            refline = self.file.readline()
            try:
                (code, val) = refline.split('=')
                if 'SPOT_ID' in code:
                    self.spot_id.append(int(val))
                else:
                    raise IOError, 'SPOT_ID not in line'
            except:
                raise IOError, 'Supposed SPOT_ID line could not be split'
            # Read shoebox
            uvm = self.file.readline()
            uvm = n.fromstring(uvm,sep=' ')[:elements].reshape(1,self.par['u_range'],self.par['v_range'])
            self.uvm = n.vstack((self.uvm,uvm))



if __name__=='__main__':
    direc = '../test'
    stem = 'debug_fabric_refl'
    grainno = 0
    setno = 0

    hst = readhst(direc,stem)
    hst.read(0,0)
