from ismumps import *
from mumpsoptions import *
from iluasmoptions import *
from EnumToString import EnumToString
from fielddisplay import fielddisplay
from EnumDefinitions import *
from checkfield import *
from MatlabFuncs import *

class solver(object):
	"""
	SOLVER class definition

	   Usage:
	      obj=solver();
	"""

	def __init__(self):    # {{{
		#MUMPS is the default solver
		if ismumps():
			self.NoneAnalysis=mumpsoptions()
		else:
			self.NoneAnalysis=iluasmoptions()

		#The other properties are dynamic
	# }}}

	def addoptions(self,analysis,*args):    # {{{
		# Usage example:
		#    md.solver=addoptions(md.solver,DiagnosticHorizAnalysisEnum(),stokesoptions());
		#    md.solver=addoptions(md.solver,DiagnosticHorizAnalysisEnum());

		#Convert analysis from enum to string
		[analysis]=EnumToString(analysis)

		#Create dynamic property if property does not exist yet
		if not hasattr(self,analysis):
#			exec("self.%s = None" % analysis)
			setattr(self,analysis,None)

		#Add solver options to analysis
		if len(args)==1:
			setattr(self,analysis,args[0])

		return self
	# }}}

	def __repr__(self):    # {{{
		s ="List of solver options per analysis:\n\n"
		for analysis in vars(self).iterkeys():
			s+="%s\n" % fielddisplay(self,analysis,'')

		return s
	# }}}

	def checkconsistency(self,md,solution,analyses):    # {{{
		for analysis in vars(self).iterkeys():
			if not getattr(self,analysis):
				md.checkmessage("md.solver.%s is empty" % analysis)

		return md
	# }}}

	def PetscFile(self,filename):    # {{{
		"""
		PETSCFILE - build petsc file

		   Build a Petsc compatible options file, from the solver model field  + return options string

		   Usage:     PetscFile(solver,filename);
		"""

		#open file for writing
		try:
			fid=open(filename,'w')
		except IOError as e:
			raise IOError("PetscFile error: could not open '%s' for writing." % filename)

		#write header
		fid.write("%s%s%s\n" % ('%Petsc options file: ',filename,' written from Matlab solver array'))

		#start writing options
		for analysis in vars(self).iterkeys():
			options=getattr(self,analysis)

			#first write analysis:
			fid.write("\n+%s\n" % analysis)    #append a + to recognize it's an analysis enum

			#now, write options
			for optionname,optionvalue in options.iteritems():

				if not optionvalue:
					#this option has only one argument
					fid.write("-%s\n" % optionname)
				else:
					#option with value. value can be string or scalar
					if   isinstance(optionvalue,(bool,int,long,float)):
						fid.write("-%s %g\n" % (optionname,optionvalue))
					elif isinstance(optionvalue,(str,unicode)):
						fid.write("-%s %s\n" % (optionname,optionvalue))
					else:
						raise TypeError("PetscFile error: option '%s' is not well formatted." % optionname)

		fid.close()
	# }}}

