'''
    SASSIE: Copyright (C) 2011 Joseph E. Curtis, Ph.D. 

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''
import os,sys,locale,string
import input_filter
import sassie.sasmol.sasmol as sasmol

def check_psegvariables_exist(psegvariables,glbls):
	error = []
	if psegvariables not in glbls:
		error.append('Please enter the segment variables by clicking on the button "click to enter segment information"!')
	return error

def check_segvariables(pdbfile,segvariables):
	error = []

	otmp = sasmol.SasMol(0)
	otmp.read_pdb(pdbfile,fastread=True)
	totnsegments = len(set(otmp.segname()))

	if len(segvariables)!=totnsegments:
		error.append('The number of segments is not equal to that from the pdb file!')
		return error

	allsnumranges=[]
	allsrlow=[]
	allsrhigh=[]
	allsegbasis=[]
	allsegname=[]
	for i in range(len(segvariables)):
		allsnumranges.append(segvariables[i][0])
		allsrlow.append(segvariables[i][1])
		allsrhigh.append(segvariables[i][2])
		allsegbasis.append(segvariables[i][3])
		allsegname.append(segvariables[i][4])

	anumranges=[] ; arlow=[] ; arhigh=[]
	for i in range(len(allsnumranges)):
		try:
			nr=locale.atoi(allsnumranges[i])
		except:
			error.append('The number of ranges "'+allsnumranges[i]+'" for segment number '+str(i)+' in the segment input fields should be an integer type!')
			return error
		if nr<1:
			error.append('The number of ranges "'+allsnumranges[i]+'" for segment number '+str(i)+' in the segment input fields should be equal/greater than 1!')
			return error
		anumranges.append(nr)

	for i in range(len(allsrlow)):
		linrlow=string.split(allsrlow[i],',')
		linrhigh=string.split(allsrhigh[i],',')
		rlow=[] ; rhigh=[]
		for k in range(len(linrlow)):
			try:
				trlow=locale.atoi(linrlow[k])
			except:
				error.append('The low resid "'+allsrlow[i]+'" for segment number '+str(i)+' in the segment input fields should be an integer array!')
				return error
			rlow.append(trlow)
		for k in range(len(linrhigh)):
			try:
				trhigh=locale.atoi(linrhigh[k])
			except:
				error.append('The high resid "'+allsrhigh[i]+'" for segment number '+str(i)+' in the segment input fields should be an integer array!')
				return error
			rhigh.append(trhigh)
		arlow.append(rlow)
		arhigh.append(rhigh)


	for i in range(len(segvariables)):
		numranges = anumranges[i]
		segbasis = allsegbasis[i]
		segname = allsegname[i]

		if segname.strip() not in otmp.segname():
			error.append('The segment name "'+segname+'" is not found in the pdb file!')
			return error
		elif segbasis.strip() not in otmp.name():
			error.append('The segment basis "'+segbasis+'" is not found in the pdb file!')
			return error

		if numranges<1:
			error.append('number of ranges '+str(numranges)+' should be equal or greater than 1!')
			return error
		if numranges!=len(arlow[i]) or numranges!=len(arhigh[i]):
			error.append('the number of low/high residue input does not match the number of ranges!')
			error.append('arlow = '+str(arlow)+' : arhigh = '+str(arhigh))
			error.append('len(arlow) = '+str(len(arlow))+' : len(arhigh) = '+str(len(arhigh)))
			error.append('numranges = '+str(numranges))
			return error

		locvariables=['resid']
		value,result=input_filter.get_pdb_complex_stats(pdbfile,segname,locvariables)
		if value==1:
			resid=map(int,result[0])
		elif value==0:
			error.append('cannot get the pdb statistics for segment '+segname)
			return error
		number_aa = resid[-1] - resid[0]+1

		for j in range(numranges):
			lowres1 = arlow[i][j]
			highres1 = arhigh[i][j]
			if(lowres1 not in resid):
		        	error.append('input pdb file, '+str(pdbfile)+' does not have low residue amino acid, '+str(lowres1)+', range = '+str(resid[0])+' : '+str(resid[-1]))
			        return error
			elif(highres1 not in resid):
			        error.append('input pdb file, '+str(pdbfile)+' does not have high residue amino acid, '+str(highres1)+', range = '+str(resid[0])+' : '+str(resid[-1]))
			        return error
			elif(lowres1 >= highres1):
			        error.append('the low-resid: '+str(lowres1)+', is greater than/equal to the high-resid: '+str(highres1)+' in segname: '+segname)
			        return error
	return error


def check_density_plot(variables,psegvariables,**kwargs):
      
    runname		= variables['runname'][0]      
    dcdfile		= variables['dcdfile'][0]      
    pdbfile		= variables['pdbfile'][0]      
    ofile		= variables['ofile'][0]        
    xlength		= variables['xlength'][0]      
    gridsp		= variables['gridsp'][0]       
    ylength		= variables['ylength'][0]      
    save_occupancy	= variables['save_occupancy'][0]        
    zlength		= variables['zlength'][0]      
    equalweights	= variables['equalweights'][0] 
    weightsfile	= variables['weightsfile'][0]  
    
    error=[]
    error = input_filter.check_name(runname)
    if(error!=[]):
        return error

    if 'no_file_check' not in kwargs:    
        path='./'

        ev,rv,wv=input_filter.check_permissions(path)
        if(not ev or not rv or not wv): 
            error.append('permission error in input file path '+path+'  [code = '+str(ev)+str(rv)+str(wv)+']')
            if(ev==False):
                error.append('path does not exist')
            elif(rv==False):
                error.append('read permission not allowed')
            elif(wv==False):
                error.append('write permission not allowed')
            return error

    ev,value=input_filter.check_pdb_dcd(pdbfile,'pdb')

    if(ev == 0):
        error.append('input pdb file, '+pdbfile+', does not exist')
        return error
    if(value == 0):
        error.append( 'input pdb file, '+pdbfile+', is not a valid pdb file')
        return error

######################### where does density_plot find the dcdfile!!!!

	#dcdfile=path+'/'+dcdfile
    ev,value=input_filter.check_pdb_dcd(dcdfile,'dcd')
	#print '0: ev,value = ',ev,value	

    if(ev == 0):
        error.append('input file, '+dcdfile+', does not exist')
        return error
	#elif(value == 0): # file is there but it is not a dcd file
    elif(dcdfile[-3:] == 'pdb'):
        ev,value=input_filter.check_pdb_dcd(dcdfile,'pdb')
		#print '1: ev,value = ',ev,value	
        if(value == 0):	# it is not a dcd or pdb file
            error.append( 'input file, '+dcdfile+', is not a valid dcd or pdb file')
            return error

        else:	# it is a pdb file
            print 'checking input pdb file against reference pdb file'
            locvariables=['name']
            value,result1=input_filter.get_pdb_stats(pdbfile,locvariables)
            value,result2=input_filter.get_pdb_stats(dcdfile,locvariables)
            if(result1 != result2):
                error.append('reference pdb file '+pdbfile+' and input file '+dcdfile+' are not compatible')
                print 'result1 = ',result1
                print 'result2 = ',result2
                return error

    else:	# check if pdb and dcd file match
        value=input_filter.certify_pdb_dcd(pdbfile,dcdfile)
		#print '2: value = ',value	
        if(value == 0):
            error.append('pdbfile '+pdbfile+' and dcdfile '+dcdfile+' are not compatible (different number of atoms)')
            return error


    if(xlength < 0.0 or ylength < 0.0 or zlength < 0.0):
        error.append( 'boxlengths need to be > 0, lengths = '+str(xlength)+','+str(ylength)+','+str(zlength))
        return error
    elif(gridsp <= 0):
        error.append('grid spacing needs to be > 0, grid spacing = '+str(gridsp))
        return error
#elif(nregions < 1):
#error.append( 'need at least one regions, nregions = '+str(nregions))
#return error
    elif(equalweights != 0 and equalweights != 1):
        error.append( 'equalweights == 0 for "no" and 1 for "yes", equalweights = '+str(equalweights))
        return error

    elif(save_occupancy != "Y" and save_occupancy != "N"):
        error.append('save occupancy data needs to be either "Y" or "N": you entered: '+save_occupancy)
        return error

#elif(len(lowregions) != nregions):
#error.append( 'the number of low region amino acids does not match the number of regions, lowregions = '+str(lowregions)+' nregions = '+str(nregions))
#return error
#elif(len(highregions) != nregions):
#error.append( 'the number of high region amino acids does not match the number of regions, highregions = '+str(highregions)+' nregions = '+str(nregions))
#return error

    locvariables=['resid']
    value,result=input_filter.get_pdb_stats(pdbfile,locvariables)
    resid=map(int,result[0])

#    if(resid[0] != 1):
#        error.append('amino acid residues in starting pdbfile '+pdbfile+' must start at resid = 1 : '+str(resid[0]))
#        return error

    number_aa = resid[-1] - resid[0] + 1

#for i in xrange(nregions):
#thislow=lowregions[i]
#thishigh=highregions[i]
#if(thislow > number_aa or thishigh > number_aa):
#error.append('either your lowregions or highregions extend beyond the number of residues in the protein: lowregions = '+str(lowregions)+' highregions = '+str(highregions)+' number aa = '+str(number_aa))
#
#return error	
#if(thishigh < thislow):
#error.append('high regions < low regions, highregions = '+str(highregions)+' lowregions = '+str(lowregions))
#return error
    if(equalweights == 0):
        error=input_filter.check_file_exists(weightsfile)	
        if(len(error)>0):
            error.append('weight file not readable or does not exist')
            return error

	### check if the weights file has at least one non-zero value

## 	structure, X2, weight
##	1       11.462422       0.000000

        try:
            infile = open(weightsfile,'r').readlines()
            if(len(infile)<1):
                error.append("no lines in your weights file : "+weightsfile)
            else:
                sum = 0.0
                for i in xrange(len(infile)):
                    lin = string.split(infile[i])
                    if(lin[0][0] != "#"):
                        this_value = locale.atof(lin[2])
                        sum += this_value
                if(sum <= 0.0):
                    error.append("all weights in weights file are zero : "+weightsfile)
                    return error
        except:
            error.append("unable to open and read your weights file : "+weightsfile)	
            return error
	

    lerror = check_segvariables(pdbfile,psegvariables)
    if len(lerror):
        #error.append('failed to check segvariables in the complex filter!')
        error.append(lerror)
        return error

    return error



