import sys
import os
import string

basedir=os.path.dirname(__file__)
sys.path.insert(0, basedir)


import ItemGUI
import command

class item:
    def __init__(self, len=0, tipo=None, scelte={}, formato=None, nome=None, stopFunction=None):
        self.len=len
        self.tipo=tipo
        self.scelte=scelte
        self.formato=formato
        self.nome=nome
        self.stopFunction=stopFunction
        self.intermezzo=""
        self.token=""
        self.attuale=""
    def estrai(self, linea, setta=1):
        if( type(self.len)==type(1)):
            token=linea[:self.len]
            if(setta):
                self.setta(token)
            return linea[self.len:]
        else:
            print self.len
            print "STOPPA DI ", linea
            pos, intermezzo=self.stopFunction(linea, self.len)
            print "RISULTATO  ", pos, " " ,len(intermezzo)
            # if( pos>=self.len[0] and pos <self.len[1]):
            token=linea[:pos]
            print "TOKEN ", token
            if(setta):
                self.setta(token)
            resto=linea[pos+len(intermezzo):]
            return resto
##            else:
##                token=line[:self.len[1]]
##                self.setta(token)
##                resto=linea[self.len[1]:]
##                return resto
                
                

    def setta(self, token):
        self.token=token
        if( self.tipo is None):
            pass
        elif( type(self.tipo)==type("")):
            self.attuale = token
        elif( type(self.tipo)==type(1)):
            if(token==" "*self.len or string.strip(token)=="" ):
                self.attuale=0
            else:
                self.attuale = string.atoi(token)
        elif( type(self.tipo)==type(1.0)):
            if(token==" "*self.len or string.strip(token)=="" ):
                self.attuale=0.0
            else:
                self.attuale = string.atof(token)

    def ceccaCond(self, cond):
        val=self.attuale
        print " cecco ", cond
        print " val est ", val
        command="res=("+cond+")"
        exec(command)
        return res
    
    def cercaScelta(self):
        found=None
        for cond in self.scelte.keys():
            res=self.ceccaCond(cond)
            if(res):
                found = cond
                break
        if( found is None):
            return  ( None, self.scelte.keys()[0], self.scelte.values()[0])
        else:
            return  (  found , self.scelte[found])


    def getTesto(self):
        testo=""
        if(type(self.tipo)==type("")):
            if( type(self.len)==type(1)):
                testo=" "*(self.len-len(self.attuale)  )  +  self.attuale
            else:
                print "GETTO TESTO " , self.attuale
                pos, intermezzo=self.stopFunction(self.attuale, self.len)
                testo=self.attuale[:pos]+intermezzo
                print "  RISUL:ATO  " , testo," " , len(intermezzo)
        elif(self.tipo is None):
            res= self.token
        elif(type(self.tipo)==type(1)):
            if(string.strip(self.token)==""):
                testo=" "*self.len
            # elif(self.attuale==0):
            #     testo=" "*self.len
            else:
                testo=str(self.attuale)
                if(len(testo)>self.len):
                    raise " len(testo)>self.len "
                testo=" "*(self.len-len(testo))+testo
        elif(type(self.tipo)==type(1.0)):
            if(self.formato is None):
                raise " formato dovrebbe esserci per floats "
            else:
                if(self.attuale==""):
                    self.attuale=0
                formato=self.formato
                if( formato[-1]=="e" and abs(self.attuale)>1.0e-3):
                    formato=formato[:-1]+"f"
                testo=formato %(self.attuale)
                testo=magrisci(testo)
                testo=" "*(self.len-len(testo)) + testo
        return testo

def ThreeSpaces(s,leng):
    pos=string.find( s[leng[0]:],"   ")
    if(pos==-1):
        res=[min(len(s), leng[1]), "   "*(len(s)<=leng[1]-3)]
        if(leng[1]-res[0]<3):
            res[1]=" "*(leng[1]-res[0])
            return res 
        else:
            return res
    else:
        return leng[0]+pos, "   "

    
def magrisci(s):
    pos=string.find(s,"e")
    if(pos==-1):
        pos=len(s)-1
        isexp=0
    else:
        pos=pos-1
        isexp=1
    sta=pos
    while(s[sta]=="0"):
        sta=sta-1
    if(s[sta]=="."):
        if(isexp or  s[:sta] !="0"):
            sta=sta-1
        else:
            sta=min(sta+1,pos)
    res=s[:sta+1]+s[pos+1:]
    return res
            


def leggilinee(fn):
    f=open(fn,"r")
    linee=[]
    for linea in f:
        if string.lstrip(linea)[:2]=="-1" :
            break
        linee.append(linea)
    return linee


def getControlsItems():
    itemlist=[]
    itemlist.append(
        item(len=1,
             tipo=1,
             nome="ITPOW",
             scelte={"val==1 or val>2": " print SCF iteration information (NITER, DELT, ALFM); this information is sent to the monitor screen if IW6 <0" ,
                     "val>1" : " call POWER to print <r**m>"
                     }
             )
        )

    itemlist.append(
        item(len=1,
             tipo=1,
             nome="ITPVU",
             scelte={
        "val>0" : "print Fk and Gk",
        "val>1":  "print Coulomb interaction energies ", 
        "val>2":  "print wavefunction overlap integrals",
        "val>3":  "print HFS potentials (RU, RUEE, etc)", 
        "val>4":  "print HX or HF potentials (Vnl) ",
        "val>5":  "in SCHEQ, print relativistic contribution to potential"
        }
             )
        )
    
    itemlist.append(
        item(len=1,
             tipo=1,
             nome="IPTEB",
             scelte={
        "val>0":" print EE, JJJ, R(JJJ), AZ ",
        "val>1":" print Ekin, etc ",
        }
             )
        )

    
    itemlist.append(
        item(len=2,
             tipo=1,
             nome="NORBPT",
             scelte={
        "val<0":" do not print wavefunctions ",
        "val>0":" print first two and last NORBPT wavefunctions at every fifth mesh point ",
        "val>5":" print continuum wavefunctions at every mesh point (for configurations 1, 5, 10, 15, ... only, if 0<NORBPT<6)  any, write on tape 2 or 7 the last |NORBPT| wavefunctions (at least 2; if |NORBPT|=9, write all wavefunctions) "
        }
             )
        )



    itemlist.append(
        item(len=1,
             tipo=1,
             nome="IZHXBW",
             scelte={
        "val>0":" in HF8, calculate and print all quantities using the (HX) input wavefunctions (primarily to give zeta calculated by the Blume-Watson method; of no great use, as the Blume-Watson method is now used in RCN as well as in HF8) "
           }
             )
        )



    itemlist.append(
        item(len=2,
             tipo=1,
             nome="IPHFWF",
             scelte={
        "val>0":" in HF8, print the last |IHFWF| wavefunctions at every mesh point ",
        "val<0":" same, except print at only every fourth mesh point ",
        "val==9 or val==-9":" print all wavefunctions "
        }
             )
        )


    itemlist.append(
        item(len=2,
             tipo=1,
             nome="IHF",
             scelte={
        "val==0":" signifies an RCN calculation only (hence, do not load HF8) ",
        "val==1":" RCN output wavefunctions are for input to HF8 (via tape 7, rather than for RCN2 (via tape 2); if IREL > 1, RCN calculation of radial integrals is skipped; if IREL=0 and TOLEND < 1.E-4, only ZETA1 is called (to calculate relativistic energy correction for Eav in HF8) ",
       "val==2":" carry out a Hartree-Fock calculation within RCN "
        }
             )
        )


    itemlist.append(
        item(len=3,
             tipo=1,
             nome="IBB",
             scelte={
        "val!=0":"sets the outer boundary of the atom at mesh point IBB; do not use this option, as it is not completely debugged.",
        "val==0":"Safe option"
        }
             )
        )

    itemlist.append(
        item(len=2,
             tipo=1.0,
             formato="%2.1f",
             nome="TTOLSTB",
             scelte={
        "1==1":" it's a referring calculation parameter of the Hartree-Fock calculation; when DELTA(cycle parameter) < TOLSTB , RCN31 begin the wavefunctions calculation by those of the subroutine SCHEQ.DELTA is a difference between the calculated potential and that of the preceeding cycle."
        }
             )
        )
    

    itemlist.append(
        item(len=5,
             tipo=1.0,
             formato="%5.1e",
             nome="TOLKM2",
             scelte={
        "1==1":"it's a control parameter related to calculation potential; when DELTA < TOLKM2, RCN31 stop the calculation of the pure HFS potential, and begin with an HX or HF calculation, in the manner that depends on the value of KUT (see De Groot manual for explanations). In this case TOLKM2=1.0"
        }
             )
        )


    itemlist.append(
        item(len=10,
             tipo=1.0,
             formato="%10.1e",
             nome="TOLEND",
             scelte={
        "1==1":"is the maximum permissible value of DELTA (the absolute value of the change in RU) for ending the SCF iteration (see the main program, statements number 530-550 and 700-780). "
        }
             )
        )

    
    

    itemlist.append(
        item(len=10,
             tipo=1.0,
             formato="%10.1e",
             nome="THRESH",
             scelte={
        "1==1":"is the maximum permissible fractional change in the value of the eigenvalue E to end the eigenvalue iteration (SCHEQ, statements 805 and 205).   "
        }
             )
        )

    
 
    itemlist.append(
        item(len=2,
             tipo=1,
             nome="KUTD",
             scelte={
        "val==-2":"it's related to KUT, wich select the type of calculation on the potential .",
        "val!=-2":"WARNING Documentation I found on the web doesnt tell much. But it looks like it is often -2"
        }
             )
        )
 
    itemlist.append(
        item(len=2,
             tipo=1,
             nome="KUT",
             scelte={
        "val ==1":"UNUSUAL  HFS calculation with no tail cutoff (KUT=1)",
        "val ==0": "USUAL HFS  with tail cutoff (KUT=0)  ",
        }
             )
        )
 
    itemlist.append(
        item(len=1,
             tipo=1,
             nome="IVINTI",
             scelte={
        " val == 0 ":"USUAL 	 no call of subroutine VINTI",
        "val  >0 ":" 	Vinti integrals calculated and printed",
        "val  > 1":" 	some debugging information printed"
        }
             )
        )

    itemlist.append(
        item(len=1,
             tipo=1,
             nome="IREL",
             scelte={
        "val==0":"If IREL=0, relativistic terms are omitted from the differential equations (HX or HF)",
        "val>0":"if IREL > 0, these terms are included (HXR or HFR).",
        "val>1":"If IREL > 1, approximate Breit magnetic and retardation energies will be included, provided the dimensions of QNL are the same as those of PNL.",
        "val>3":"If IREL > 3, some diagnostic printouts will occur. "
        }
             )
        )
    
    

    itemlist.append(
        item(len=2,
             tipo=1,
             nome="MAXIT",
             scelte={
        "val==90":"COMMON value : is the maximum allowable number of SCF iterations; if convergence has not been reached within MAXIT cycles, the calculation is continued for 4 more cycles with diagnostic printout produced via NPR > 0 (RCN, 710-729)",
        "val!=90":" Other value : is the maximum allowable number of SCF iterations; if convergence has not been reached within MAXIT cycles, the calculation is continued for 4 more cycles with diagnostic printout produced via NPR > 0 (RCN, 710-729) "
        }
             )
        )

   

    itemlist.append(
        item(len=2,
             tipo=1,
             nome="NPR",
             scelte={
        "val!=0":"not 0, diagnostic potentials and diagnostic wavefunctions are printed during the course of the RCN SCF iteration ",
        "val==0":" diagnostic potentials and diagnostic wavefunctions are NOT  printed during the course of the RCN SCF iteration "
      }
             )
        )


    
    


    itemlist.append(
        item(len=5,
             tipo=1.0,
             formato="%5.5f",
             nome="EXF10",
             scelte={
        "val==1.0":"Kohn and Sham's modified value for the coefficient of Slater's exchange term for an HFS calculation with no tail cutoff (KUT=1) or with tail cutoff (KUT=0) (RCN 411-417).",
        "val==1.5":"EXF10=1.5 is Slater's original value  "
        }
             )
        )

    


    itemlist.append(
        item(len=5,
             tipo=1.0,
             formato="%5.5f",
             nome="EXFM1",
             scelte={
        "val==0":"are values of k1, k3, and k2, respectively, for KUT=-1 in an HX calculation [Phys. Rev.163, 54 (1967), Eqs. (13)-(14) or TASS, Eqs. (7.49)-(7.50)]. Provided IHF=0, EXFM1=0.0 will give a Hartree calculation for KUT=-1, and KUT=-2 gives an HS calculation. (CAO and CA1 are no longer read in from the control card, but simply set to 0.5 and 0.7, respectively, in the code.) "
        }
             )
        )


    itemlist.append(
        item(len=5,
             tipo=1.0,
             formato="%5.5f",
             nome="EMX",
             scelte={
        "val==0.0":"EMX(column 61th-65th):selection parameter for the construction of the mesh points (es: 0.0)."
        }
             )
        )




    itemlist.append(
        item(len=5,
             tipo=1.0,
             formato="%5.5f",
             nome="CORRF",
             scelte={
        "val==0.0":" factor for correlation ",
        "val==1.0":" factor for correlation ",
        }
             )
        )
    



    itemlist.append(
        item(len=5,
             tipo=1,
             nome="IW6",
             scelte={
        "-6":"I dont knwo what it is but from what I see around it is quite often(always) set to -6"
        }
             )
        )
    
    return itemlist
    
    

def getCalcoloItems():
    itemlist=[]
    itemlist.append(
        item(len=1,
             tipo=1,
             nome="NHFTRM",
             scelte={"val==0":"no LS terms, non HF calculation (HFX, averaged configuration...",
                     "val>0":"Number of LS terms for which HF calculations are to be made"
                     }
             )
        )
    
    itemlist.append(
        item(len=4,
             tipo=1,
             nome="IZ",
             scelte={"1==1":"Atomic number (fixed point)"}
             )
        )
    

    
    itemlist.append(
        item(len=3,
             tipo=1,
             nome="IBB1",
             scelte={"val==0":"default easy choice",
                     "val>0":"For this configuration only, overrides the value IBB read from the control card, provided IBB1 > KO, the storage dimension for the maximum number of orbitals. If 0.LE.IBB1.LE.KO, then the input value is interpreted as a quantity N1SCF, and IBB1 is set to zero. All radial functions with serial number equal to or less than N1SCF are held frozen at their form in the preceding configuration; see examples in Section J. and  K.. http://www.ucd.ie/speclab/Cowandocs/RCN/RCN_node20.html#secrcn_ii_j "
                     }
             )
        )
    
    
    
    itemlist.append(
        item(len=2,
             tipo=1,
             nome="NSPECT",
             scelte={"1==1":"1+degree of ionization (1=neutral, 2=singly ionized, 3=doubly ionized, etc.)"}
             )
        )
    
    itemlist.append(
        item(len=[6,18],
             tipo="s",
             nome="CONF",
             stopFunction= ThreeSpaces,
             scelte={"1==1":"BCD configuration label (eg, Ca I 4s 3d), for identification purposes only. (For clarity of RCN2 and RCG output, columns 11-16 should contain the element and ion stage, and the configuration label should be restricted to columns 17-24). "}             
             )
        )
    itemlist.append(
        item(len=52,
             tipo="s",
             nome="FREE FOR.",
             scelte={"1==1":"""The subshell nl values and occupation numbers come next: any number of subshells up to eight, each with format A3,A2 (or A2,A2 is OK if n<10). 
KUT (1 or -1) and/or EE8 (any number of digits, with decimal point) come last, in either order, default values being 0 and 0.0.
For example, for a free p electron (denoted by using n=99) with kinetic energy of 13.6268 Ry, the nominal formats would require:
99p 13.626793, instead for a filled 3d shell it would be : 3d10 """}             
             )
        )
    
    return itemlist


def settaItems(itemsList, linea):
     for item in itemsList:
        linea=item.estrai(linea)
   
       
def main():
    if(len(sys.argv)==2):
        linee = leggilinee(sys.argv[1])
    itemsContr = getControlsItems ()

    count=0
    for item in itemsContr:
        print count+1, "-" ,count+item.len,"   " ,item.nome
        count=count+item.len

    if(len(sys.argv)==2):
        settaItems(   itemsContr, linee[0]) 

    itemsCalc = getCalcoloItems ()
    
    if(len(sys.argv)==2):
        settaItems(   itemsCalc, linee[1]) 
    
    import qt
    app=  qt.QApplication([])

    principale=qt.QTabWidget()

    mw = ItemGUI.mainWindow(itemsContr,principale )
    principale.addTab(mw,"Control Card")
    mw.aggiornaLinea()

    mw1 = ItemGUI.mainWindow(itemsCalc, principale)
    principale.addTab(mw1,"Configuration Card")
    mw1.aggiornaLinea()

    cw = command.Form1(principale)
    masterObject=MasterObject(itemsContr, itemsCalc, cw,mw,mw1)
    
    cw.connect(cw.runcowan, qt.SIGNAL("clicked()"), masterObject.runCowan)
    cw.connect(cw.loadExample  , qt.SIGNAL("clicked()"), masterObject.loadExample )

    principale.addTab(cw,"commands")

    principale.show()

    app.setMainWidget(principale)    

    app.exec_loop()
    
class MasterObject:
    def __init__(self, itemsContr, itemsCalc, cw, mw, mw1):
        self.itemsContr=itemsContr
        self.itemsCalc=itemsCalc
        self.cw=cw
        self.mw = mw
        self.mw1= mw1        
        self.cw.examplesTE.setReadOnly(1)
        self.cw.examplesTE.setText(in36_examples)

    def runCowan(self):
        s="" 
        for ob in self.itemsContr:
            s=s+ob.getTesto()
        s=s+"\n"
        for ob in self.itemsCalc:
            s=s+ob.getTesto()
        s=s+"\n"
        s=s+"   -1\n"
        f=open("in36","w")
        f.write(s)
        f.close()

        basedir=os.path.dirname(__file__)

        
        os.system(basedir+"/a.out")
        
    def loadExample(self):
        para, pos = self.cw.examplesTE.getCursorPosition()
        configuration = str(self.cw.examplesTE.text(para))
        if(para==0):
            return
        if( checkLast(self.cw.examplesTE.text(para-1))):
            return
        while(1):
            para-=1
            if( para==0 or checkLast(self.cw.examplesTE.text(para-1)) ):
                control=str(self.cw.examplesTE.text(para))
                break
        settaItems(self.itemsContr,control)
        settaItems(self.itemsCalc, configuration)
        self.mw .aggiornaAllItems()
        self.mw1.aggiornaAllItems()

def checkLast(s):
            s=string.strip(str(s))
            if(s=="-1"):
                return 1
            else:
                return 0






in36_examples="""2  -9    2   10  0.2    5.e-08    1.e-11-2   090   1.0  0.65  0.0 0.00   -6
   19    6K VI  3s2 3p2       3s2 3p2
   19    6K VI  3p4           3p4
   19    6K VI  3p 3d         3s2 3p 3d
   -1
2  -9    2   10  0.2    5.e-08    1.e-11-2   190   1.0  0.65  0.0 0.00   -6
   55    1Cs III 5s2 5p5    5s2 5p5
   55    1Cs III 5p4 6p     5s2 5p4 6p
   55    1Cs III 5p4 7p     5s2 5p4 7p
   55    1Cs III 5p4 4f     5s2 5p4 4f
   55    1Cs III 5p4 5f     5s2 5p4 5f
   55    1Cs III 5p4 6h     5s2 5p4 6h
   55    1Cs III 5s 5p6     5s  5p6
   55    1Cs III 5p4 6s     5s2 5p4 6s
   55    1Cs III 5p4 7s     5s2 5p4 7s
   55    1Cs III 5p4 5d     5s2 5p4 5d
   55    1Cs III 5p4 6d     5s2 5p4 6d
   55    1Cs III 5p4 5g     5s2 5p4 5g
   -1
2  -9    2   10  1.0    5.e-08    1.e-11-2   090   1.0  0.65  0.0 0.00   -6
   18    1Ar II 3p5       3p5
   18    1Ar II 3p4 4p    3p4 4p
   18    1Ar II 3p4 4s    3p4 4s
   18    1Ar II 3p4 5s    3p4 5s
   18    1Ar II 3p4 3d    3p4 3d
   18    1Ar II 3p4 4d    3p4 4d
   18    1Ar II 3p4 5d    3p4 5d
   -1
2   5    2   10  1.0    5.e-08    1.e-11-2   190   1.0  0.65  0.0 0.00   -6
   54    1Xe II 5p5      5s2 5p5
   54    1Xe II 5p4 6p   5s2 5p4 6p
   54    1Xe II 5p4 6s   5s2 5p4 6s
   54    1Xe II 5p4 7s   5s2 5p4 7s
   54    1Xe II 5p4 5d   5s2 5p4 5d
   54    1Xe II 5p4 6d   5s2 5p4 6d
   54    1Xe II 5p4 7d   5s2 5p4 7d
   54    1Xe II 5s5p5 6p   5s 5p5 6p
   -1
2   5    2   10  1.0    5.e-08    1.e-11-2   190   1.0  0.65  0.0 0.00   -6
   36    1Kr II 4p5       4p5
   36    1Kr II 4p4 5p    4p4 5p
   36    1Kr II 4p4 5s    4p4 5s
   36    1Kr II 4p4 6s    4p4 6s
   36    1Kr II 4p4 4d    4p4 4d
   36    1Kr II 4p4 5d    4p4 5d
   -1
2  -5    2   10  1.0    5.e-08    1.e-11-2   190   1.0  0.65  0.0 0.00   -6
   55    1Cs III 5s2 5p5    5s2 5p5
   55    1Cs III 5p4 6p     5s2 5p4 6p
   55    1Cs III 5p3 5d6s   5s2 5p3 5d 6s
   55    1Cs III 5p4 5d     5s2 5p4 5d
   55    1Cs III 5p3 5d6p   5s2 5p3 5d 6p
   -1
   55    1Cs III 5s 5p6     5s  5p6
   55    1Cs III 5p4 6s     5s2 5p4 6s
   55    1Cs III 5p4 5d     5s2 5p4 5d
   -1
   55    1Cs IV 5s25p4    5s2 5p4
   55    1Cs IV 5s 5p5    5s  5p5
   -1
3   5    2   10  2.0    5.e-08    1.e-11-2   199   1.0  0.65  0.0 0.00   -6
   32   -5Ge I  4p2      4p2
   32   -5Ge I  4p 4d    4p 4d
   26    1Fe I  4s23d6   4s2 3d6
   26    1Fe I  4s 3d7   4s  3d7
   57    1La I  6s2 4f   6s2 4f
   57    1La I  6s 4f2   6s  4f2
   58    1Ce II 6s2 4f   6s2 4f
   58    1Ce II 6s 4f2   6s  4f2
   59    1Pr+2  6s2 4f   6s2 4f
   59    1Pr+2  6s 4f2   6s  4f2
   92    1U I   6d 5f3   7s2 6d 5f3
   92    1U I   5f4      7s2 5f4
   93    1Np II 6d 5f3   7s2 6d 5f3
   93    1Np II 5f4      7s2 5f4
   94    1Pu+2  6d 5f3   7s2 6d 5f3
   94    1Pu+2  5f4      7s2 5f4
   79   60Au+51 3d8 4s2    3d8 4s2
   79   60Au+51 3d8 4s4p   3d8 4s 4p
   79   60Au+51 3d8 4s4d   3d8 4s 4d
   67    1Ho I  f11 6s2    4f11 6s2
   67    1Ho I  f11 6s7p   4f11 6s 7p
   67    1Ho I  f12 6s     4f12 6s
   68    1Er II f11 6s2    4f11 6s2
   68    1Er II f11 6s7p   4f11 6s 7p
   68    1Er II f12 6s     4f12 6s
   69    1Tm+2  f11 6s2    4f11 6s2
   69    1Tm+2  f11 6s7p   4f11 6s 7p
   69    1Tm+2  f12 6s     4f12 6s
   -1
"""


main()



