from EnumDefinitions import *
from EnumToString import EnumToString

def AnalysisConfiguration(solutiontype): #{{{
	"""
	ANALYSISCONFIGURATION - return type of analyses, number of analyses 

		Usage:
			[analyses, numanalyses]=AnalysisConfiguration(solutiontype);
	"""

	if   solutiontype == StressbalanceSolutionEnum():
		numanalyses=5
		analyses=[StressbalanceAnalysisEnum(),StressbalanceVerticalAnalysisEnum(),StressbalanceSIAAnalysisEnum(),SurfaceSlopeAnalysisEnum(),BedSlopeAnalysisEnum()]

	elif solutiontype == SteadystateSolutionEnum():
		numanalyses=7 
		analyses=[StressbalanceAnalysisEnum(),StressbalanceVerticalAnalysisEnum(),StressbalanceSIAAnalysisEnum(),SurfaceSlopeAnalysisEnum(),BedSlopeAnalysisEnum(),ThermalAnalysisEnum(),MeltingAnalysisEnum()]

	elif solutiontype == ThermalSolutionEnum():
		numanalyses=2 
		analyses=[ThermalAnalysisEnum(),MeltingAnalysisEnum()]

	elif solutiontype == EnthalpySolutionEnum():
		numanalyses=1 
		analyses=[EnthalpyAnalysisEnum()]

	elif solutiontype == MasstransportSolutionEnum():
		numanalyses=1 
		analyses=[MasstransportAnalysisEnum()]

	elif solutiontype == BalancethicknessSolutionEnum():
		numanalyses=1 
		analyses=[BalancethicknessAnalysisEnum()]

	elif solutiontype == SurfaceSlopeSolutionEnum():
		numanalyses=1 
		analyses=[SurfaceSlopeAnalysisEnum()]

	elif solutiontype == BalancevelocitySolutionEnum():
		numanalyses=1 
		analyses=[BalancevelocityAnalysisEnum()]

	elif solutiontype == BedSlopeSolutionEnum():
		numanalyses=1 
		analyses=[BedSlopeAnalysisEnum()]

	elif solutiontype == GiaSolutionEnum():
		numanalyses=1
		analyses=[GiaAnalysisEnum()]

	elif solutiontype == TransientSolutionEnum():
		numanalyses=9 
		analyses=[StressbalanceAnalysisEnum(),StressbalanceVerticalAnalysisEnum(),StressbalanceSIAAnalysisEnum(),SurfaceSlopeAnalysisEnum(),BedSlopeAnalysisEnum(),ThermalAnalysisEnum(),MeltingAnalysisEnum(),EnthalpyAnalysisEnum(),MasstransportAnalysisEnum()]

	elif solutiontype == FlaimSolutionEnum():
		numanalyses=1 
		analyses=[FlaimAnalysisEnum()]

	elif solutiontype == HydrologySolutionEnum():
		numanalyses=3 
		analyses=[BedSlopeAnalysisEnum(),SurfaceSlopeAnalysisEnum(),HydrologyShreveAnalysisEnum(),HydrologyDCInefficientAnalysisEnum(),HydrologyDCEfficientAnalysisEnum()]

	else:
		raise TypeError("solution type: '%s' not supported yet!" % EnumToString(solutiontype)[0])

	return analyses,numanalyses
#}}}

def ismodelselfconsistent(md):
	"""
	ISMODELSELFCONSISTENT - check that model forms a closed form solvable problem.

	   Usage:
	      ismodelselfconsistent(md),
	"""

	#initialize consistency as true
	md.private.isconsistent=True

	#Get solution and associated analyses
	solution=md.private.solution
	analyses,numanalyses=AnalysisConfiguration(solution)

	#Go through a model fields, check that it is a class, and call checkconsistency
	fields=vars(md)
#	for field in fields.iterkeys():
	for field in md.properties():

		#Some properties do not need to be checked
		if field in ['results','debug','radaroverlay']:
			continue

		#Check that current field is an object
		if not hasattr(getattr(md,field),'checkconsistency'):
			md.checkmessage("field '%s' is not an object." % field)

		#Check consistency of the object
		exec("md.%s.checkconsistency(md,solution,analyses)" % field)

	#error message if mode is not consistent
	if not md.private.isconsistent:
		raise RuntimeError('Model not consistent, see messages above.')

