from __future__ import with_statement
import os,sys,copy,shutil
import common,manager,parse


def CallCrankFromCCP4i2(ccp4i2crank, xmlfile=None, inpfile=None, defaults=False):
  import CCP4PluginScript
  os.chdir(ccp4i2crank.workDirectory)
  parser=parse.parse()
  parser.pars_arg.dirout = ccp4i2crank.workDirectory
  if xmlfile:
    f = open(xmlfile,'r')
    parser.pars_arg.xmlin = f
  elif inpfile:
    f = open(inpfile,'r')
    parser.pars_arg.keyin = f
  else:
    common.Error('Crank process could not be initialized.')
  global crank_logfile, stdout_save
  with open(os.path.join(ccp4i2crank.workDirectory,'log.txt') ,'w', 1) as crank_logfile:
    stdout_save = sys.stdout
    sys.stdout = crank_logfile
    error=0
    try:
      crank = parser.ParseAndRun(ccp4i2crank,defaults)
    except:
      error=1
    else:
      crank.ccp4i2job = ccp4i2crank
    sys.stdout = stdout_save
    f.close()
    if error:
      raise
  # register output objects from the last step...
  if not defaults:
    if hasattr(crank.processes[-1],'ccp4i2job'):
      for outd_name in crank.processes[-1].ccp4i2job.container.outputData._dataOrder:
        if outd_name in ccp4i2crank.container.outputData._dataOrder:
          last_gui2_obj = getattr(crank.processes[-1].ccp4i2job.container.outputData, outd_name)
          setattr( ccp4i2crank.container.outputData, outd_name, last_gui2_obj )
          filepath=OutFilesDirMatch(str(last_gui2_obj),crank)
          getattr(ccp4i2crank.container.outputData, outd_name).setFullPath(filepath)
    crank.ccp4i2.reportStatus(CCP4PluginScript.CPluginScript.SUCCEEDED)
  #else:
  #  shutil.rmtree(ccp4i2crank.workDirectory)
  return crank

def RegisterProcessToCCP4i2(ccp4i2crank, process):
  import CCP4PluginScript
  sys.stdout = stdout_save
  subjob = ccp4i2crank.makePluginObject(pluginName='crank2_'+process.nick, pluginTitle=process.name[0].upper()+process.name[1:])
  if subjob is None:
    subjob = ccp4i2crank.makePluginObject(pluginName=process.name.capitalize(), dummy=True)
  process.SetRunDir(subjob.workDirectory)
  process.ccp4i2job = subjob
  sys.stdout = crank_logfile
  # "dummy" update of the program.xml file - might be moved into crank2 later on
  shutil.copy(os.path.join(subjob.workDirectory,'..',process.nick+'.xml'), os.path.join(subjob.workDirectory,'..','program.xml'))

# annotations for the ccp4i2 output containers (does not seem possible to assign in xml?)
annotations = { 'FPHOUT_HAND2':    '"Best" density - other hand (not chosen)', \
                'FPHOUT_2FOFC':    '2mFo-DFc weighted density coef.', \
                'FPHOUT_DIFFANOM': 'Difference anomalous diff. map coef.', \
                'FPHOUT_HL':       '"Best" phases, Hendrickson-Lattman coef.', \
                'FPHOUT':          '"Best" electron density map coefficients', \
                'XYZOUT_HAND2':    'Anom. substr. - other hand (not chosen)', \
                'XYZOUT_SUBSTR':   'Anomalous substructure coordinates', \
                'XYZOUT':          'Model coordinates' \
              }

def RegisterOutputToCCP4i2(process,error):
  import CCP4PluginScript
  import CCP4ErrorHandling
  import CCP4XtalData
  sys.stdout = stdout_save
  i2job=process.ccp4i2job
  if error:
    i2job.reportStatus(CCP4PluginScript.CPluginScript.FAILED)
    raise
  else:
    for outd_name in i2job.container.outputData._dataOrder:
      outd_obj = getattr(i2job.container.outputData, outd_name)
      if outd_name.startswith('XYZOUT'):
        if outd_name=='XYZOUT':
          out_obj=process.out.Get(filetype='pdb',typ=('partial+substr','partial',))
        elif outd_name=='XYZOUT_SUBSTR':
          out_obj=process.out.Get(filetype='pdb',typ='substr')
        elif outd_name=='XYZOUT_HAND2':
          out_obj=process.other_phas.out.Get(filetype='pdb')
        if out_obj is not None:
          filepath=OutFilesDirMatch(out_obj,process)
          outd_obj.setFullPath(filepath)
      elif outd_name.startswith('FPHOUT'):
        if outd_name=='FPHOUT_HAND2':
          out_obj=process.other_phas.out.Get('mapcoef',filetype='mtz',typ=('best','combined'))
        elif outd_name=='FPHOUT_2FOFC':
          out_obj=process.out.Get('mapcoef',filetype='mtz',typ='weighted')
        elif outd_name=='FPHOUT_DIFFANOM':
          out_obj=process.out.Get('mapcoef',filetype='mtz',typ='anom-diff')
        else:
          out_obj=process.out.Get('mapcoef',filetype='mtz',typ=('best','combined'))
        if out_obj is not None:
          filepath=OutFilesDirMatch(out_obj,process,filetype='mtz')
          outd_obj.setOutputPath(projectId=i2job.projectId(), relPath=i2job.relPath())
          if outd_name=='FPHOUT_HL':
            outd_obj.contentFlag.set(CCP4XtalData.CPhsDataFile.CONTENT_FLAG_HL)
            error = i2job.splitHklout([outd_name,], [out_obj.GetLabel('hla')+','+out_obj.GetLabel('hlb')+','+out_obj.GetLabel('hlc')+','+out_obj.GetLabel('hld'),], infile=filepath)
          else:
            error = i2job.splitHklout([outd_name,], [out_obj.GetLabel('f')+','+out_obj.GetLabel('ph'),], infile=filepath)
          #print 'taskSplitHklout',error.report()
          if error.maxSeverity()>CCP4ErrorHandling.SEVERITY_WARNING:
            i2job.reportStatus(CCP4PluginScript.CPluginScript.FAILED)
      if outd_name in annotations:
        outd_obj.annotation.set(annotations[outd_name])
#    process.ccp4i2job.container.outputData.pdb.subType = 1
    process.ccp4i2job.reportStatus(CCP4PluginScript.CPluginScript.SUCCEEDED)
    sys.stdout = crank_logfile

def OutFilesDirMatch(out_obj,process,filetype=None):
  # makes sure the output file in the output directory expected by ccp4i2
  try:
    f=out_obj.GetFileName(filetype=filetype)
  except AttributeError:
    f=out_obj
  f2=os.path.join(process.ccp4i2job.workDirectory, os.path.basename(f))
  if not os.path.isfile(f2):
    shutil.copy(f,f2)
  return f2
