#! /usr/bin/env ccp4-python
#
#     Copyright (C) 2005 Ronan Keegan
#
#     This code is distributed under the terms and conditions of the
#     CCP4 Program Suite Licence Agreement as a CCP4 Application.
#     A copy of the CCP4 licence can be obtained by writing to the
#     CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK.
#
# A MrBUMP wrapper for Molrep and Phaser and Refmac, used for
# running nosharefilesys jobs, where there is no shared filesystem nor Python
#

import os, sys, string
import time
import shutil
import refmacEXE
import pdbtools
import subprocess
import shlex


if not os.environ.has_key('CCP4'):
    raise RuntimeError, 'CCP4 not found'
if not os.environ.has_key('CBIN'):
    raise RuntimeError, 'CBIN not found'

def check_exist(filename):
   if not os.path.exists(filename):
      sys.stdout.write("ERROR: Cannot find executable for CONDOR run\n")
      sys.stdout.write(filename+"\n")
      sys.stdout.write("\n")
      sys.exit(1)


class CombinedEXE:
   """ A class to run multiple executables on CONDOR system
       with Windows or Linux machines """

   def __init__(self, sub_funct, host_os, mrbump_keywords):
      self.host_os=host_os
      self.mrbump_keywords=mrbump_keywords

      # NB: This is where the executables should be kept
      if self.host_os=='nt':
        self.molrepEXE = os.path.join(os.environ["CCP4"], "share", "mrbump", "bin", "molrep.exe")  
        self.refmacEXE = os.path.join(os.environ["CCP4"], "share", "mrbump", "bin", "refmac5.exe")  
        self.phaserEXE = os.path.join(os.environ["CCP4"], "share", "mrbump", "bin", "phaser.exe")  
      else:
        self.molrepEXE = os.path.join(os.environ["CCP4"], "share", "mrbump", "bin", "molrep")  
        self.refmacEXE = os.path.join(os.environ["CCP4"], "share", "mrbump", "bin", "refmac5")  
        self.phaserEXE = os.path.join(os.environ["CCP4"], "share", "mrbump", "bin", "phaser")  

      # Confirm that executables exist
      check_exist(self.molrepEXE)
      check_exist(self.refmacEXE)
      check_exist(self.phaserEXE)
        

      # Confirm that zip script and data zip exist
      self.unzip_script = os.path.join(os.environ["CCP4"], "share", "mrbump", "data", "condor", "unzip2.vbs")
      self.data_zip = os.path.join(os.environ["CCP4"], "share", "mrbump", "data", "condor",  "data2.zip")

      check_exist(self.unzip_script)
      check_exist(self.data_zip)

      # Confirm that parameter files exist
      self.environ_def = os.path.join(os.environ["CCP4"], "share", "mrbump", "data", "condor", "environ.def")
      self.default_def = os.path.join(os.environ["CCP4"], "share", "mrbump", "data", "condor",  "default.def")

      check_exist(self.environ_def)
      check_exist(self.default_def)

      self.input_file_list=[]
      self.output_file_list=[]
      self.command_line_dict={}
      self.keywords_dict={}
      self.logfile_dict={}
      self.mode_dict={}
      self.runType_list=[]
      self.soln_found=False
      self.submitFunction=sub_funct

      self.SG_Codes={"P31" : "144", "P32" : "145", "P3112" : "151", "P3212" : "153", 
                     "P3121" : "152", "P3221" : "154", "P41" : "76", "P43" : "78", 
                     "P4122" : "91", "P4322" : "95", "P41212" : "92", "P43212" : "96", 
                     "P61" : "169", "P65" : "170", "P62" : "171", "P64" : "172", 
                     "P6122" : "178", "P6522" : "179", "P6222" : "180", "P6422" : 
                     "181", "P4332" : "212", "P4132" : "213"}

      self.ENANT_SG={"144" : "145", "145" : "144", "151" : "153", "153" : "151", 
                     "152" : "154", "154" : "152", "76" : "78", "78" : "76", 
                     "91" : "95", "95" : "91", "92" : "96", "96" : "92", "169" : "170", 
                     "170" : "169", "171" : "172", "172" : "171", "178" : "179", 
                     "179" : "178", "180" : "181", "181" : "180", "212" : "213", "213" : "212"}

      try:
         self.debug=eval(os.environ['MRBUMP_DEBUG'])
      except:
         self.debug=False

      self.local_debug = False


   #def add_keyword(self, runType, keyword):
   #   self.keywords_dict[runType].append(keyword)
      
   def check_contrast(self):
      """ Check the molrep logfile of the job for the Contrast value. """
 
      f=open(self.logfile, "r")
      
      line=f.readline()
      while line:
         if "Contrast =" in line:
            try:
               self.contrast=float(string.split(line)[-1])
            except:
               sys.stdout.write("MR Log: error extracting Contrast value from Molrep log file\n")
               sys.stdout.write("\n")

         line=f.readline()

      f.close()

   def setup_run(self, input_file_list, output_file_list, logfile, runType, mode="A", script="",  keyword_list=[], keyfile="", cmdline_xtras=""):
      """ Function to setup an executable which runs within a process which
          run 'nosharefilesys' on a cluster
          'nosharefilesys' means that it submits to a cluster where execution
          environment does not have python nor shared filesystem
      """
      self.input_file_list+=input_file_list
      self.output_file_list+=output_file_list
      self.logfile_dict[runType]=logfile
      self.mode_dict[runType]=mode
      self.runType_list.append(runType)
      key=""

      # Set the keywords for the job 
      if keyword_list!=[]:
         # Use host_os to tailor line endings
         if self.host_os=='nt':
            for keyword in keyword_list:
               key+=keyword+"\r\n"
         else:
            for keyword in keyword_list:
               key+=keyword+"\n"

      elif keyfile!="":
         # Read keywords from the keyword file 
         kfile=open(keyfile, "r")
         line=kfile.readline()
         while line:
            # Use host_os to tailor line endings
            if self.host_os!='nt':
               key+=line
            else:
               key+=line.rstrip('\n')+'\r\n'
            line=kfile.readline()
         kfile.close()

      self.keywords_dict[runType]=key

      # Set up command line
      command_line=""
      if runType=="MOLREP":
        
         # Add the function mode keyword
         self.keywords_dict[runType] = self.keywords_dict[runType] + "FUN " + self.mode_dict[runType]
         if self.host_os=='nt':
            self.keywords_dict[runType]+="\r\n"
         else:
            self.keywords_dict[runType]+="\n"
 

      # Set the command line and add the executable as an input file
      if runType=="MOLREP":
         command_line=os.path.basename(self.molrepEXE)
         self.input_file_list.append(self.molrepEXE)
      elif runType=="PHASER":
         command_line=os.path.basename(self.phaserEXE)
         self.input_file_list.append(self.phaserEXE)
      elif runType=="REFMAC":
         command_line=os.path.basename(self.refmacEXE)
         self.input_file_list.append(self.refmacEXE)

      self.command_line_dict[runType]=command_line+cmdline_xtras
       


   def run(self, working_DIR):

      # Add in the CCP4 data dir, and a script to unzip it
      self.input_file_list += [self.data_zip, self.unzip_script, self.environ_def, self.default_def]
      

      # Change to the running directory
      os.chdir(working_DIR)

      # Give a header output
      sys.stdout.write("#################################################\n")
      if "MOLREP" in self.runType_list:
         if self.mode_dict.get("MOLREP","") != "T":
            sys.stdout.write("Running Molrep...... \n")
         else: 
            sys.stdout.write("Running Molrep in enantiomorphic SG...... \n")
      if "PHASER" in self.runType_list:
         sys.stdout.write("\n")
         sys.stdout.write("Running Phaser...... \n")
      if "REFMAC" in self.runType_list:
         sys.stdout.write("\n")
         sys.stdout.write("Running Refmac ...... \n")
      sys.stdout.write("#################################################\n")
      sys.stdout.write("\n")

      # Open a pipe to the job
      # Echo the command line in debug mode
      if self.local_debug:
         sys.stdout.write("\n")
         sys.stdout.write("======================\n")
         sys.stdout.write("Command lines:\n")
         sys.stdout.write("======================\n")
         for runType in self.runType_list:
            sys.stdout.write(self.command_line_dict[runType]+"\n")
         sys.stdout.write("\n")

      # Output the keywords if in debug mode
      if self.local_debug:
         sys.stdout.write("#########################\n")
         sys.stdout.write("Keyword input:\n")
         sys.stdout.write("#########################\n")
         for runType in self.runType_list:
            sys.stdout.write("\n")
            sys.stdout.write(self.keywords_dict[runType])
            sys.stdout.write("\n")
         sys.stdout.write("Running submit_function in:"+working_DIR+"\n")
         sys.stdout.write("\n")
         time.sleep(2)


      job_id=self.submitFunction(working_DIR, self.input_file_list,
          self.output_file_list, self.command_line_dict, self.keywords_dict,
          self.logfile_dict, self.runType_list, self.mrbump_keywords, self.debug)
      return job_id
