
"""
======================COPYRIGHT/LICENSE START==========================

write.py: code for CCPN data model and code generation framework

Copyright (C) 2011  (CCPN Project)

=======================================================================

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

A copy of this license can be found in ../../../license/LGPL.license

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


======================COPYRIGHT/LICENSE END============================

for further information, please contact :

- CCPN website (http://www.ccpn.ac.uk/)

- email: ccpn@bioc.cam.ac.uk

=======================================================================

If you are using this software for academic purposes, we suggest
quoting the following references:

===========================REFERENCE START=============================
R. Fogh, J. Ionides, E. Ulrich, W. Boucher, W. Vranken, J.P. Linge, M.
Habeck, W. Rieping, T.N. Bhat, J. Westbrook, K. Henrick, G. Gilliland,
H. Berman, J. Thornton, M. Nilges, J. Markley and E. Laue (2002). The
CCPN project: An interim report on a data model for the NMR community
(Progress report). Nature Struct. Biol. 9, 416-418.

Rasmus H. Fogh, Wayne Boucher, Wim F. Vranken, Anne
Pajon, Tim J. Stevens, T.N. Bhat, John Westbrook, John M.C. Ionides and
Ernest D. Laue (2005). A framework for scientific data modeling and automated
software development. Bioinformatics 21, 1678-1684.

===========================REFERENCE END===============================

"""
import sys, os, operator, json

from ccpnmr.integrator.core import Io as intIo
#from ccpnmr.integrator.core import Util as intUtil
#from ccpnmr.integrator.plugins.Unio import Util as unioUtil
from memops.universal import Io as uniIo

pluginName = 'ccpnmr.integrator.plugins.Cyana'

initFileName = 'init.cya'

programBin = '${CYANA_HOME}'

def write(nmrCalcRun, targetDir):
  """ Write input files for Program run
    Input:
      nmrCalcRun: NmrCalc.Run
      targetDir: destination directory.
  """

  intIo.writeDataFiles(nmrCalcRun, targetDir)

  jsonDict = intIo.makeJsonDict(nmrCalcRun)

  # write properties file
  propFile = uniIo.joinPath(targetDir, intIo.propFileName)
  print 'About to write', propFile
  open(propFile,'w').write(json.dumps(jsonDict, sort_keys=True,
                                      indent=intIo.propIndent))

  # Write program setup file
  fileNameObj = nmrCalcRun.findFirstRunParameter(name='fileNameSetup')
  importJsonName = 'cyana2ccpn.json'
  if fileNameObj is not None:

    # write init.cya
    initFile = uniIo.joinPath(targetDir, initFileName)
    rmsdrange = jsonDict['RunParameter'].pop('rmsdrange')
    seqFile =  jsonDict['RunParameter'].pop('fileNameSequence')
    text = """# Cyana init file - Generated by CcpNmr Integrator
rmsdrange:=%s
cyanalib
read seq %s
""" % (rmsdrange, seqFile)
    open(initFile,'w').write(text)

    # write main command file
    filePath = uniIo.joinPath(targetDir, fileNameObj.textValue)
    importFilePath = uniIo.joinPath(targetDir, importJsonName)
    writeSetupFile(filePath, jsonDict)
    writeImportJson(importFilePath,jsonDict)


def writeImportJson(filePath,jsonDict):

  """
  write JSON file for importing cyana output

  """

  importJsonDict = {"pdbFile":"final.pdb",
"distanceRestraints":[],
"cyaFiles":["finalstereo.cya"],
"dihedralRestraints":[],
"rdcRestraints":[],
"noaFiles":["cycle7.noa"]}
  if jsonDict["ConstraintStoreData"]:
    for constraintList in jsonDict["ConstraintStoreData"]:
      if "fileName" in constraintList:
        if isinstance(constraintList['fileName'],list):
         for item in constraintList['fileName']:
           if 'aco' in item:
             # print item.split('.')[1]
             importJsonDict['dihedralRestraints'].append(item)
           elif item.split('.')[1] == 'upl':
             # print item.split('.')[1]
             importJsonDict['distanceRestraints'].append(item)
        elif isinstance(constraintList['fileName'],str):
          if constraintList['fileName'].split('.')[1] == 'aco':
            importJsonDict['dihedralRestraints'].append(constraintList['fileName'])
          elif constraintList['fileName'].split('.')[1] == 'upl':
            importJsonDict['distanceRestraints'].append(constraintList['fileName'])

  open(filePath, 'w').write(json.dumps(importJsonDict, sort_keys=True,
                                      indent=intIo.propIndent))

def writeSetupFile(filePath, jsonDict):
  """ Write program-specific setup file with parameters in paramDict
  """

  skipTags = ('firstSeqId', 'lastSeqId', 'calcMode')

  lineFormat = "%s  :=  %s\n"

  fp = open(filePath, 'w')

  try:

    fp.write("# Cyana command file - Generated by CcpNmr Integrator\n\n")


    for item in sorted(jsonDict['RunParameter'].items()):
      if item[0] not in skipTags:
        fp.write(lineFormat % item)
    fp.write('\n')


    if 'MeasurementListData' in jsonDict:
      dd = jsonDict['MeasurementListData'][0]
      tag = 'prot'
      fp.write(lineFormat % (tag, dd['fileName']))
      fp.write('\n')

    if "ConstraintStoreData" in jsonDict:
      ll = jsonDict["ConstraintStoreData"][0]["fileName"]
      if isinstance(ll,str):
        restraints = ll
      else:
        restraints = ','.join(x for x in ll)
      fp.write("restraints:="+restraints)
      fp.write('\n')

    structures = '%s,%s' % (jsonDict['noStartStructures'],jsonDict['noEndStructures'])
    fp.write(lineFormat % ("structures",structures))



    # NBNB TBD Modify to allow different calc modes?
    tag = 'programCommandString'
    ### programCommandString changed to accept xeasy peaklists from $peaks2, rather than xpk peaklists from $peaks
    fp.write('\n%s\n' % jsonDict[tag])

  finally:
    fp.close()


def prepareLocalExecution(nmrCalcRun, targetDir):
  """ return [procArgs, targetDir, logFile list for later, local execution
  And carry out any preliminary commands
  """

  # Set up parameters for program call
  shellParObj = nmrCalcRun.findFirstRunParameter(name='programCall')
  if shellParObj is None:
    raise Exception("Parameter name=programCall not found")
  else:
    shellCall = shellParObj.textValue

  executeScript = os.path.join(os.path.expandvars(programBin), shellCall)
  executeScript2 = os.path.join(os.path.expandvars(programBin), 'cyanatable')

  fileNameObj = nmrCalcRun.findFirstRunParameter(name='fileNameSetup')
  if fileNameObj is None:
    raise Exception("no 'fileNameSetup' parameter found")
  filePath = uniIo.joinPath(targetDir, fileNameObj.textValue)



  procargs = [executeScript, filePath]
  procargs2 = [executeScript2]

  #
  return (procargs,targetDir,procargs2)

if __name__ == '__main__':
  """ Run write function from command line.
  Input is projectDir NmrCalcRun.IDstring
  projectDir must contain the desired project (and no others)
  NmrCalcRun.IDstring is of the form
  '%s+%s' % (NmrCalcStore.guid, Run.serial)
  """

  print '### Cyana.write:', len (sys.argv), sys.argv[1:]

  if len(sys.argv) >= 3:

    print '### Cyana.write nArgs >= 3:'

    # set up input
    junk, projectDir, nmrCalcRunId = sys.argv[:3]

    print '### Cyana.write got data :', projectDir, nmrCalcRunId

    if len(sys.argv) >= 4:
      print '### Cyana.write nArgs >= 4:'
      targetDir = sys.argv[3]
    else:
      print '### Cyana.write targetDir is None'
      targetDir=None

    #print '### Cyana.write about to run prepareStdWmsRun'
    #print '###', pluginName, projectDir, nmrCalcRunId, targetDir
    #intIo.prepareStdWmsRun(pluginName, projectDir, nmrCalcRunId, targetDir)
    #print '### Cyana.write finished prepareStdWmsRun'

    # NB necessary.
    # As side effect prints message that passes newCalcId to WMS Java
    nmrCalcRun = intIo.getNmrCalcRun(projectDir, nmrCalcRunId, pluginName)

  else:
    print "Usage: write projectDir NmrCalcRun.IDstring targetDir(optional)"


