# Imports from delivery/script
import ScriptEnvironment
import Utils
from Utils import Utils, product
from PCygniParameter import PCygniParameter
from PCygniPhysicalModel import PCygniPhysicalModel

# Imports from cassis
from eu.omp.irap.cassis.gui import PanelView

# Imports from Java 
from javax.swing   import JOptionPane

# Imports from Python
import os


class ParameterNameError(Exception):
	"""Raised when the name of the parameter is invalid"""
	pass
		

class PCygniComponent(object):
	def __init__(self, continuum="continuum-0", **parameters):
		super(PCygniComponent, self).__init__()
		self.continuum = self.checkContinuum(continuum)

		for name, value in parameters.items():
			self.checkParameterName(name)

			# Create the parameters
			if value.has_key("step"):
				p = PCygniParameter(name, value['min'], value['max'], step=value['step'], 
								 log_mode=value.get('log_mode', False))
			elif value.has_key("nstep"):
				p = PCygniParameter(name, value['min'], value['max'], nstep=value['nstep'], 
								 log_mode=value.get('log_mode', False))
			else:
				raise ValueError("You must provide step or nstep to create a PCygniParameter instance.")

			# Set the parameter as an attribute
			setattr(self, name, p)

		# Correct the parameters names if necessary (temp -> tex or tkin)
		self.parameters = parameters

		# Store the names of the parameters in a predefined order
		self.names = [name for name in Utils.ORDERED_PARAMETER_NAMES\
					  if name in self.parameters.keys()]

	def __str__(self):
		return "PCygniComponent(%s)" % (", ".join(self.names))

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

		using defined constants. (cf Utils)

		Throws
		------
		ParameterNameError when the parameter name is not valid

		"""
		if name not in Utils.MANDATORY_PARAMETERS:
			msg = "%s is not a valid parameter name.\n" % name
			msg += "Choose between:\n"
			msg += "- mandatory parameters: %s\n" % ", ".join(Utils.MANDATORY_PARAMETERS)
			raise ParameterNameError(msg)

	def checkContinuum(self, value):
		msg = "Can't find the continuum file:\n%s.\nTake continuum-0 as default?" % value
		if os.path.exists(value) or\
		   os.path.exists(os.path.join(Utils.CONTINUUM_DIR, value)):
			return value
		else:
			answer = JOptionPane.showConfirmDialog(None, msg,
												   "Wrong continuum file",
												   JOptionPane.YES_NO_OPTION)

			if answer == JOptionPane.YES_OPTION:
				print("Set continuum to 0.")
				return "continuum-0"
			else:
				sys.exit("Exiting.")

	def createPhysicalModel(self):
		parametersList	  = (getattr(self, x) for x in self.parameters)
		parametersValues  = (x.getValues() for x in parametersList)
		valueCombinations = product(*parametersValues)
		combinations      = (zip(self.parameters.keys(), x) for x in valueCombinations)
		combinations      = [dict(x) for x in combinations]
		physicalModel	  = [PCygniPhysicalModel(x) for x in combinations]

		# Extra constant parameters for the self
		constParams = ['continuum']
		for constParam in constParams:
			[setattr(pSet, constParam, getattr(self, constParam)) for pSet in physicalModel]

		return physicalModel


	__repr__ = __str__
		

# vim: set noet fdm=indent:
