

from CCP4TaskWidget import CTaskWidget
from PyQt4 import QtCore,QtGui
import CCP4XtalData,CCP4XtalWidgets
from CCP4ErrorHandling import *

#-------------------------------------------------------------------
class CTaskimport_merged(CTaskWidget):
#-------------------------------------------------------------------

# Subclass CTaskWidget to give specific task window
  TASKNAME = 'import_merged'
  TASKVERSION = 0.1
  TASKMODULE='data_entry'
  TASKTITLE='Import merged reflection data'
  SHORTTASKTITLE='Import merged'
  DESCRIPTION = 'Import reflection data in any format, report on contents and create CCP4i2 data objects'

  def __init__(self,parent):
    CTaskWidget.__init__(self,parent)

  def drawContents(self):

    self.openFolder(folderFunction='inputData',followFrom=False)

    self.createLine ( [ 'subtitle','Select a merged data file' ] )
    self.createLine ( [ 'widget','HKLIN' ] )
    self.openSubFrame(toggle=[ 'HKLINISMTZ', 'open', [ False ] ] )
    self.createLine ( [ 'subtitle','Enter additional information' ] )
    self.createLine ( [ 'widget', 'SPACEGROUPCELL' ] )
    self.createLine ( [ 'label','Wavelength','widget', 'WAVELENGTH' ] )
    self.createLine ( [ 'label', 'Crystal name','widget','CRYSTALNAME','label', 'Dataset name','widget','DATASETNAME' ] )
    self.closeSubFrame()
    self.createLine (['subtitle','Any FreeR in the input file will be automatically read and completed'])

    # We almost certainly want to keep whatever was set when the data was saved so dont call updateFromFile
    #self.updateFromFile(force=False)
    # Beware connecting to any dataChanged from HKLIN got a signal at run time when dbFileId set on the HKLIN
    self.connect(self.container.inputData.HKLIN,QtCore.SIGNAL('dataChanged'),self.updateFromFile)
    self.getWidget('SPACEGROUPCELL').validate()

  def fix(self):
    # disconnect updateFromFile() cos that and unSetAll() were being called by processing of the  HKLIN file (ef setDbFileId())
    self.disconnect(self.container.inputData.HKLIN,QtCore.SIGNAL('dataChanged'),self.updateFromFile)
    if self.container.guiParameters.HKLINISMTZ:
      for item in [ 'SPACEGROUPCELL' , 'WAVELENGTH', 'CRYSTALNAME', 'DATASETNAME' ]:
        self.container.inputData.get(item).setQualifiers( { 'allowUndefined' : True } )
        self.getWidget(item).validate()
    return CErrorReport()
    
  def updateFromFile(self,force=True):
    # Explicit call to CGenericREflnDataFile.getFileContent() otherwise CData properties code gets it wrong
    self.unSetAll()

    #print '***CTaskimport_merged.updateFromFile1', self.container.inputData.HKLIN
    self.container.inputData.HKLIN.loadFile()
    self.container.guiParameters.HKLINISMTZ = (self.container.inputData.HKLIN.getFormat() == 'mtz')
    fileContent = self.container.inputData.HKLIN.getFileContent()
    #print '***CTaskimport_merged.updateFromFile2',type(fileContent),fileContent,self.container.inputData.HKLIN.getMerged()
    #import traceback; traceback.print_stack(limit=6)
    
    if self.container.inputData.HKLIN.getMerged() == 'unmerged':
      mess = QtGui.QMessageBox.warning(self,'Importing merged file','This apppears to be an unmerged file - please use the Data Reduction task to import it')
      self.container.inputData.HKLIN.unSet()
      self.container.inputData.SPACEGROUPCELL.unSet()
      return
    else:
      #print 'CTaskimport_merged.updateFromFile fileContent',type(fileContent),fileContent.get()
      #print "fileContent", fileContent.wavelengths, fileContent.datasets, fileContent.crystalNames
      if force or fileContent.cell.isSet():
        self.container.inputData.SPACEGROUPCELL.cell.set(fileContent.cell.fix(fileContent.cell.get()))
      if force or fileContent.spaceGroup.isSet():
        self.container.inputData.SPACEGROUPCELL.spaceGroup.set(fileContent.spaceGroup)
      print '***CTaskimport_merged.updateFromFile wavelengths ',fileContent.contents('wavelengths')
      if fileContent.contents('wavelengths') is not None and fileContent.wavelengths.isSet() and len(fileContent.wavelengths)>0:
        # extract relevant wavelength
        for wavelength, dataset in zip(fileContent.wavelengths, fileContent.datasets):
          if dataset != 'HKL_base':
            break         
        print "wavelength, dataset", wavelength, dataset
        self.container.inputData.WAVELENGTH.set(self.container.inputData.WAVELENGTH.fix(wavelength.__float__()))
      elif fileContent.contents('wavelength') is not None and fileContent.wavelength.isSet():
        self.container.inputData.WAVELENGTH.set(self.container.inputData.WAVELENGTH.fix(fileContent.wavelength.__float__()))
      elif force:
        self.container.inputData.WAVELENGTH.unSet()
        

    if self.container.inputData.HKLIN.getFormat() == 'mtz':
      self.selectObsColumns()
    else:
      try:
        if fileContent.datasetName.isSet() and len(fileContent.datasetName)>=1:
          self.container.inputData.DATASETNAME.set(str(fileContent.datasetName))
        elif force:
          self.container.inputData.DATASETNAME.unSet()
      except:
       pass
      try:
        if fileContent.crystalName.isSet() and len(fileContent.crystalName)>=1:
          self.container.inputData.CRYSTALNAME.set(str(fileContent.crystalName))
        elif force:
          self.container.inputData.CRYSTALNAME.unSet()
      except:
        pass
     


  def selectObsColumns(self):
    hklin = self.container.inputData.HKLIN
    mtzModel = self.container.inputData.get('HKLIN_OBS')
    mtzModel.setFullPath(str(hklin))
    mtzModel.loadFile()
    
    errors = mtzModel.validColumns()
   
    if errors.maxSeverity()>SEVERITY_WARNING:
      #print errors.report()
      if errors.count(cls=mtzModel.__class__,code=203)>0:
        QtGui.QMessageBox.warning(self,'Error in selected MTZ file','Selected MTZ file does not contain correct type of data')
        hklin.unSet()
        return
      elif errors.count(cls=mtzModel.__class__,code=204)>0 or errors.count(cls=mtzModel.__class__,code=205)>0:
        applyNow = (errors.count(cls=mtzModel.__class__,code=205)>0)
        #print 'handleBrowserOpenFile applyNow',applyNow,hklin
        self.selColDialog=CCP4XtalWidgets.CSelectColumnsWidget(parent=self,model=mtzModel,applyNow=applyNow,filename=str(hklin))
        self.connect(self.selColDialog,QtCore.SIGNAL('apply'),self.handleSelColDialogApply)
        self.connect(self.selColDialog,QtCore.SIGNAL('cancel'),self.handleSelColDialogCancel)
      else:
        pass


  def handleSelColDialogApply(self):
    contentFlag,i2Names,dataset,colLabels = self.selColDialog.getSelection()
    #print 'handleSelColDialogApply getSelection',contentFlag,i2Names,dataset,colLabels
    try:
      self.selColDialog.hide()
    except:
      pass
    jobId = self.jobId()
    projectId = self.projectId()
    mtzModel =  self.container.inputData.HKLIN_OBS
    mtzModel.setFullPath(str(self.container.inputData.HKLIN))
    #print 'handleSelColDialogApply',contentFlag,i2Names,dataset,colLabels
    error = mtzModel.splitMtz(jobId=jobId,projectId=projectId,contentFlag=None,i2Labels=i2Names,columnLabels=colLabels)
    sourceFileName = mtzModel.__dict__.get('sourceFileName','')
    if sourceFileName is None: sourceFileName = ''
    #print 'handleSelColDialogApply',error.report(),sourceFileName
    if error.maxSeverity()==SEVERITY_WARNING and error[0]['code']==212:
      mess = QtGui.QMessageBox.warning(self,self.windowTitle(),'This data is already imported as\n'+error[0]['details'])
    elif error.maxSeverity()>=SEVERITY_WARNING:
      if error[0]['code']==211:
        mess = QtGui.QMessageBox.warning(self,self.windowTitle(),'No column data selected')
      else:
        error.warningMessage(windowTitle='Splitting MTZ: '+sourceFileName,jobId=jobId,parent=self)
      self.container.inputData.HKLIN.unSet()
      
    else:
      
      mtzModel.loadFile()
      
      # columnGroup.get() is dict of form {'SIGF': 'SIGFNAT', 'F': 'FNAT'}
      columnGroup = mtzModel.__dict__['columnGroupList'][contentFlag-1].get()
      #print 'columnGroup',content_flag,columnGroup,mtzModel.CONTENT_SIGNATURE_LIST[content_flag-1]
      columns = ''
      ok = True
      for colName in mtzModel.CONTENT_SIGNATURE_LIST[contentFlag-1]:
          #print 'handleSelColDialogApply',colName,columnGroup[colName]
          if columnGroup[colName] is None or columnGroup[colName] in ['']:
            ok = False
          else:
            columns = columns+str(columnGroup[colName])+','
        
      #print 'CMiniMtzDataFileView.handleDialogApply HKLIN_OBS',self.container.inputData.HKLIN_OBS,self.container.inputData.HKLIN_OBS.exists()
      #print 'CMiniMtzDataFileView.handleDialogApply contentFlag',ok,contentFlag,columns
      
      self.selColDialog.deleteLater()
      if not ok:
        self.unSetAll(ifHklin=True)
      else:
        self.container.inputData.HKLIN_OBS_CONTENT_FLAG = contentFlag
        self.container.inputData.HKLIN_OBS_COLUMNS = columns[0:-1]
        #print 'HKLIN_OBS_COLUMNS',self.container.inputData.HKLIN_OBS_COLUMNS
        #print 'handleSelColDialogApply',mtzModel.fileContent.datasets,mtzModel.fileContent.crystalNames
        # Expect the datasets/cryalNames lists to be HKL_base and possibly the crystal/dataset for the extracted data
        self.container.inputData.DATASETNAME.set(str(mtzModel.fileContent.datasets[-1]))
        self.container.inputData.CRYSTALNAME.set(str(mtzModel.fileContent.crystalNames[-1]))
        self.container.inputData.SPACEGROUPCELL.cell.set(mtzModel.fileContent.datasetCells[-1])
        self.getWidget('DATASETNAME').validate()
        self.getWidget('CRYSTALNAME').validate()


  def handleSelColDialogCancel(self):
    self.selColDialog.hide()
    self.selColDialog.deleteLater()
    self.unSetAll(ifHklin=True)



  def unSetAll(self,ifHklin=False):

    for item in ['HKLIN_OBS','HKLIN_OBS_COLUMNS','HKLIN_OBS_CONTENT_FLAG','CRYSTALNAME','DATASETNAME']:
        self.container.inputData.get(item).unSet()       
    for item in ['WAVELENGTH','CRYSTALNAME','DATASETNAME']:
      self.getWidget(item).validate()
    if ifHklin:
      self.container.inputData.HKLIN.blockSignals(True)
      self.container.inputData.HKLIN.unSet()
      self.container.inputData.HKLIN.blockSignals(False)
