#!/usr/bin/python
# $Id$
'''
Created on May 15, 2012

@author: Denver Green
'''

USAGE = '''USAGE:

propagate_ssm [options]

Propagates the Solar System Model of the given simulation to the given date or
to the current date if a date is not specified.
'''

#------------------------------------------------------------------------------
# Imports.
#------------------------------------------------------------------------------
import sys
import os
import os.path
import logging
import sched
import time
import optparse
import fnmatch
import MOPS.Lib as Lib
import MOPS.Utilities as Utilities
import MOPS.Condor as Condor
from MOPS.SSM import SSM 
from MOPS.Instance import Instance
try:
    from ConfigParser import SafeConfigParser
except ImportError:
    from configparser import ConfigParser as SafeConfigParser

#------------------------------------------------------------------------------
# Global variables.
#------------------------------------------------------------------------------
gLogger = None

#------------------------------------------------------------------------------
# Function Definitions.
#------------------------------------------------------------------------------ 
    
def createCondorJob(inst, log_dir, out_dir, initial_dir, cmd, epoch, format, ssm_dir):
    """
    Setup the job manifesto for the Condor job.
    """
        
    # Create the job instance.
    job = open(os.path.join(log_dir, "jobfile.txt"), "w")
    job.write("universe = vanilla\n")
    job.write("executable = %s\n" % (cmd))
    job.write("arguments = --epoch %s --format %s\n" % (epoch, format))
    job.write("environment = \"PERL5LIB=/home/mops/MOPS_DEVEL/lib/perl5 PYTHONPATH=/home/mops/MOPS_DEVEL/lib/python PYTHON_EGG_CACHE=/tmp MOPS_DBINSTANCE=psmops_dgreen_test CAET_DATA=/hom\
e/mops/MOPS_DATA/caet_data ORBFIT_DATA=/home/mops/MOPS_DATA/orbfit OORB_DATA=/home/mops/MOPS_DATA/oorb PATH=/home/mops/MOPS_DEVEL/bin:/usr/local/bin:/usr/bin:/bin LD_LIBRA\
RY_PATH=/home/mops/MOPS_DEVEL/lib MOPS_HOME=/home/mops/MOPS_DEVEL\"\n")
    job.write("initialdir = %s\n" % (initial_dir))
    job.write("should_transfer_files = YES\n")
    job.write("when_to_transfer_output = ON_EXIT\n")
    job.write("notification = Error\n")

    for f in os.listdir(ssm_dir):
        if (not fnmatch.fnmatch(f, 'S*')):
            continue
        # <-- end if            
        job.write("\ninput = %s\n" % (f))
        job.write("log = %s\n" % (os.path.join(log_dir, f + '.condorlog')))
        job.write("error = %s\n" % (os.path.join(log_dir, f + '.stderr')))
        job.write("output = %s\n" % (os.path.join(out_dir, f)))
        job.write("queue\n")
    # <-- end for
    job.close()
    return job
# <-- end def
            
#------------------------------------------------------------------------------
# Entry point.
#------------------------------------------------------------------------------
def main(args=sys.argv[1:]):
    """
    
    """
    AGE = 1            # Default max age for SSM
    prop_date = None 
    
    parser = optparse.OptionParser(USAGE)
    parser.add_option('--epoch',
                      action='store',
                      dest='epoch',
                      type='int',
                      default=None,
                      help="The date specified as a modified julian date to propagate the SSM to.\n")
    parser.add_option('--dir',
                      action='store',
                      dest='ssm_dir',
                      type='string',
                      default=None,
                      help="Directory containing SSM to be propagated.\n")
    parser.add_option('--format',
                      action='store',
                      dest='format',
                      type='string',
                      default=None,
                      help="Format of the input orbit file.\n")
    parser.add_option('--instance',
                      action='store',
                      dest='instance',
                      type='string',
                      default=os.environ.get('MOPS_DBINSTANCE', None),
                      help="Name of the simulation whose SSM is to be propagated.\n")
                      
    # Verbose flag
    parser.add_option('-v',
                      action='store_true',
                      dest='verbose',
                      default=False,
                      help="Prints extra information to log file.\n")                    
    
    # Get the command line options and also whatever is passed on STDIN.
    (options, args) = parser.parse_args()
    
    # Make sure that we have what we need. 
    if(not options.instance): 
       parser.error('No --instance specified and no $MOPS_DBINSTANCE defined.') 
    # <-- end if 
    if(not options.ssm_dir): 
       parser.error('No --dir specified.') 
    # <-- end if 

    # Determine the name of MOPS DB instance.
    inst = Instance(dbname=options.instance)  


    # Get logger and set logging level. Typically set level to info.
    # Add null handler to logger to avoid the No handlers could be found
    # for logger XXX error if a handler is not found in a higher level logger
    global gLogger  
    gLogger = Utilities.getLogger()
    if (options.verbose):
        gLogger.setLevel(logging.DEBUG)
    else:
        gLogger.setLevel(logging.INFO)
    # <-- end if
     
    gLogger.info("PROPAGATE_SSM: Starting propagate_ssm")
    
    # Verify SSM directory
    if (not os.path.exists(options.ssm_dir)):
        gLogger.error("PROPAGATE_SSM: The SSM directory %s does not exist." % (options.ssm_dir))
        raise RuntimeError("PROPAGATE_SSM: The SSM directory %s does not exist." % (options.ssm_dir))
    # <-- end if
    
    # Set-up log directory
    if (options.ssm_dir):
        log_dir = os.path.join(options.ssm_dir, 'log')
        if (os.path.exists(log_dir)) :
            # Clean out log directory
            for f in os.listdir(log_dir):
                os.remove(os.path.join(log_dir,f))
            # <-- end for
        else:
            # Create log directory if necessary.
            os.mkdir(log_dir)
        # <-- end if
    # <-- end if
    
    # Set up directory that will contain the propogated SSM
    current_dir = os.path.join(options.ssm_dir, 'current')
    if not os.path.exists(current_dir):
        # Directory to contain propagate SSM does not exist, create it.
        os.mkdir(current_dir)
    # <-- end if

    if (options.epoch):
        # Set prop_date to the epoch given on the command line.
        prop_date = options.epoch
    else :
        # Set prop_date to the current UT date and convert it to a modified
        # julian date (mjd).
        prop_date = time.gmtime()
        prop_date = Lib.gd2jd(prop_date.tm_year, prop_date.tm_mon, prop_date.tm_mday)
        prop_date = Lib.jd2mjd(prop_date)
    # <-- end if
        
    # Clean out the SSM in the current directory
    for f in os.listdir(current_dir):
        os.remove(os.path.join(current_dir,f))
    # <-- end for
            
    # Create a condor job file which will be used to propagate the ssm on
    # the condor cluster
    cmd = os.path.join(inst.getEnvironment('HOMEDIR'), 'bin', 'propagateOrbits')
    job = createCondorJob(inst, log_dir, current_dir, options.ssm_dir,cmd, prop_date, options.format, options.ssm_dir)

    gLogger.info("PROPAGATE_SSM: Propagating SSM in %s to %s" % (options.ssm_dir, prop_date))
    gLogger.info("PROPAGATE_SSM: Storing propagated SSM in %s" % (current_dir))
    # Submit the job to the cluster and wait until it is done.
    gLogger.info("PROPAGATE_SSM: condor_submit %s" % (os.path.join(log_dir, job.name)))
    os.system("condor_submit %s" % (os.path.join(log_dir, job.name)))
# <-- end def

if __name__ == '__main__':
    sys.exit(main())
# <-- end if