import ScriptEnvironment
from Constants import Constants


class PhysicalModel(object):
	"""A PhysicalModel is a unique combination of the physical parameters
	for a given component.

	It is used to model a molecular spectrum in LineAnalysis.

	Usage:
		physicalModel = PhysicalModel(parameters, tbg=tbg, n=n)

	* parameters: a dictionary of the form:
				  {parameter_name : parameter_value, ...}
				  representing a unique set of parameter values
				  amongst all the possible combinations with the
				  different components
	* tbg		: the background temperature
				  [OPTIONAL, DEFAULT:2.73]

	* n			: the density of H2
				  [OPTIONAL, DEFAULT:7.5e22]

	Example:
		physicalModel = PhysicalModel({"vlsr": 11.33, "nmol": 1e14, ...})

	"""
	def __init__(self, parameters, tbg=2.73, n=7.5e22, tex= 100.0, tkin=10.0, size=3.0):
		self.tbg           = tbg
		self.n             = n
		# self.tex           = tex
		# self.tkin          = tkin
		# self.size          = size
		self.parameters    = parameters
		self.collisioner   = []
		self.collisionFile = []
		self._model        = ""
		self.interacting   = None
		self.geometry      = ""
		self.continuum     = None
		self.names      = [name for name in Constants.ORDERED_PARAMETER_NAMES\
						   if name in self.parameters.keys()]

		# Set the parameters names as attributes
		for name, value in parameters.items():
			self.checkParameterName(name)
			setattr(self, name, value)

	def checkParameterName(self, name):
		"""Check the name of a parameter in the following categories:
			- mandatory
			- optional
			- collisioner

		using defined constants. (cf Constants)

		"""
		if name not in Constants.ALL_PARAMETERS:
			msg = "%s is not a valid parameter name.\n" % name
			msg += "Choose between:\n"
			msg += "- mandatory parameters: %s\n" % ", ".join(Constants.MANDATORY_PARAMETERS)
			msg += "- optional parameters: %s\n" % ", ".join(Constants.OPTIONAL_PARAMETERS)
			msg += "- or collisioner parameters: %s\n" % ", ".join(Constants.COLLISIONER_PARAMETERS)
			raise ValueError(msg)

	# The model is deduced from the temperature
	def get_model(self):
		if hasattr(self, "tex"):
			return "Lte"
		elif hasattr(self, "tkin"):
			return "Radex"
		else:
			return "Unknown"

	# TODO Add checks for the model
	def set_model(self, value):
		if hasattr(self, "tex"):
			if value.lower() == 'lte':
				self._model = 'Lte'
		elif hasattr(self, "tkin"):
			if value.lower() == 'radex':
				self._model = 'Radex'
		else:
			self._model = "Unknown"

	model = property(get_model, set_model)

	def __str__(self):
		attrs = []
		attrs.extend(self.names)
		attrs.append("tbg")
		strings = ["nmol = %.2g" % self.nmol]
		strings += ["%s = %.2f" % (x, getattr(self, x)) for x in attrs if x != 'nmol']
		# Append model
		strings.append("model = %s" % self.model)

		return "PhysicalModel(%s)" % (", ".join(strings))

	__repr__ = __str__


# vim: set noet fdm=indent:
