import datetime
import os
import shutil

def solve(md,solutionenum,*args):
	"""
	SOLVE - apply solution sequence for this model
 
	    Usage:
	       md=solve(md,solutionenum,varargin)
	       where varargin is a list of paired arguments of string OR enums
 
	    solution types available comprise:
	 		 - DiagnosticSolutionEnum
	 		 - PrognosticSolutionEnum
	 		 - ThermalSolutionEnum
	 		 - SteadystateSolutionEnum
	 		 - TransientSolutionEnum...
	 		 - BalancethicknessSolutionEnum
	 		 - BedSlopeSolutionEnum
	 		 - SurfaceSlopeSolutionEnum
	 		 - HydrologySolutionEnum
	 		 - FlaimSolutionEnum
 
	   extra options:
	       - loadonly : does not solve. only load results
 
	    Examples:
	       md=solve(md,DiagnosticSolutionEnum);
	"""

	#recover and process solve options
	options=pairoptions('solution_type',solutionenum,*args)
	options=process_solve_options(options)

	#recover some fields
	md.private.solution=options['solution_type']
	cluster=md.cluster

	#check model consistency
	print "checking model consistency"
	if solutionenum == FlaimSolutionEnum:
		md.private.isconsistent=True
		md.mesh.checkconsistency(md,solutionenum)
		md.flaim.checkconsistency(md,solutionenum)
		if not md.private.isconsistent:
			raise RuntimeError("Model not consistent, see messages above.")
	else:
		ismodelselfconsistent(md)

	#First, build a runtime name that is unique
	c=datetime.datetime.now()
	md.private.runtimename="%s-%02i-%02i-%04i-%02i-%02i-%02i-%i" % (md.miscellaneous.name,c.month,c.day,c.year,c.hour,c.minute,c.second,os.getpid())

	#if running qmu analysis, some preprocessing of dakota files using models
	#fields needs to be carried out. 
	if md.qmu.isdakota:
		md=preqmu(md,options)

	#flaim analysis
	if options['solution_type'] == FlaimSolutionEnum:
		md=flaim_sol(md,options)
		md.private.solution=EnumToString(options['solution_type'])
		return md

	#Do we load results only?
	if options['loadonly']:  
		md=loadresultsfromcluster(md)
		return md

	#Wite all input files
	marshall(md)                                           # bin file
	md.solver.PetscFile(md.miscellaneous.name+'.petsc')    # petsc file
	cluster.BuildQueueScript(md.miscellaneous.name,md.private.runtimename,md.private.solution,md.settings.io_gather,md.debug.valgrind,md.debug.gprof)    # queue file

	#we need to make sure we have PETSC support, otherwise, we run with only one cpu: 
	if not ispetsc:
		print "PETSC support not included, running on 1 cpu only!"
		cluster.np=1

	#Stop here if batch mode
	if strcmpi(options['batch'],'yes'):
		print 'batch mode requested: not launching job interactively'
		print 'launch solution sequence on remote cluster by hand'
		return md

	#Launch job
	modelname = md.miscellaneous.name
	filelist  = [modelname+'.bin ',modelname+'.petsc ',modelname+'.queue ']
	if md.qmu.isdakota:
		filelist.append(modelname+'.qmu.in')
	cluster.LaunchQueueJob(md.miscellaneous.name,md.private.runtimename,filelist)

	#did we even try to run? if so, wait on lock
	if strcmpi(options['upload'],'on'):
		print 'solve done uploading test decks'
		return md

	#wait on lock
	if md.settings.waitonlock>0:
		#we wait for the done file
		islock=waitonlock(md)
		if islock==0:    #no results to be loaded
			print 'The results must be loaded manually with md=loadresultsfromcluster(md).'
		else:            #load results
			print 'loading results from cluster'
			md=loadresultsfromcluster(md)

	#post processes qmu results if necessary
	if md.qmu.isdakota:
		if not strncmpi(options['keep'],'y',1):
			shutil.rmtree('qmu'+str(os.getpid()))

	return md

