from eu.omp.irap.cassis.gui.model.lteradex import LteRadexModel, LteRadexPanel, LteRadexControl
from eu.omp.irap.cassis.common import MoleculeDescription, CommentedSpectrum, ComponentMode
from eu.omp.irap.cassis.gui.model.parameter.lteradexcomponent import ComponentDescription
from eu.omp.irap.cassis.gui.model.table import CassisTableDisplayEvent
from eu.omp.irap.cassis.gui.model import CassisModel
from eu.omp.irap.cassis.file import FileManagerVOTable
from eu.omp.irap.cassis.gui import PanelView
from eu.omp.irap.cassis.common import Telescope, SideBand, TypeFrequency
from eu.omp.irap.cassis.gui.model.parameter.observing import ObservingMode
from eu.omp.irap.cassis.common.axes import UNIT
from eu.omp.irap.cassis.cassisd import ServerImpl
from eu.omp.irap.cassis.gui.model.parameter.modeltuning import TuningMode
from eu.omp.irap.cassis.gui.model.parameter.threshold import QuantumNumberThresholdModel
from eu.omp.irap.cassis.gui.model.parameter.continuum import ContinuumParameters

from java.util import ArrayList
from java.io import File
from javax.swing import JOptionPane
import ScriptUtilities
import ScriptConstants

from eu.omp.irap.cassis.common import ParameterDescription

class LteRadexLA(object):
	choice = None


	def getResult(self):
		return self.result
	
	# manque affichage en line avec resolution et dsh
	# et calcul des freq a partir de line, deltaFreq et bandwidth
	# line, deltaFreq, dsb=False, sideBand="LSB",bandwidth=4
	# tunningModel.setResolution(deltaFreq)
	# tunningModel.setResolutionUnit(UNIT.MHZ)
	#### Suite du code
	# line or range, bandwidth, deltaFreq
	# if len(line)==1:
	#		tunningModel.setTuningMode(TuningMode.LINE)
	#		tunningModel.setLineValue(line[0])
	#		tunningModel.setBandValue(bandwidth)
	#		tunningModel.setBandUnit(UNIT.GHZ)
    #
	#		#dsb
	#		tunningModel.setDsbSelected(dsb)
	#		if dsb==True:
	#			sideBandObject = SideBand.USB
	#			if sideBand.upper() == "LSB":
	#				sideBandObject = SideBand.LSB
	#			tunningModel.setSideBand(sideBandObject)
	#			tunningModel.setLoFreq(telescopeObject.computeLoFreq(line[0], sideBandObject) )
	#	else:
	#		tunningModel.setTuningMode(TuningMode.RANGE)
	#
	
	#=======================
	# run LteRadex model
	def run(self, freqs, lineFrequency, telescope, tmb2ta, components,  eup=[0.0, 150.0],
         jup=["*", "*"], kup=["*", "*"], lup=["*", "*"], mup=["*", "*"], tbg = 2.73,
         aijMin=0., rms=0., warning=True, typeFreq = TypeFrequency.REST, vlsrOffset=0.0,
         observing_mode = ObservingMode.PSDBS, continuum=0):
		self.model = LteRadexModel()
	
		self.model.getFrequencyModel().setFrequency(typeFreq)
	
		#telescope
		telescopeObject =  Telescope(telescope)
		self.model.getModelTuningModel().setTelescope(telescopeObject)
		
		#tmb2ta
		self.model.getParametersModel().setSelectedTelescope(telescope)
		self.model.getParametersModel().setTmbTa(tmb2ta)
		
		self.model.getTbgModel().setTbg(tbg)
		self.model.getObservingModel().setObserving(observing_mode)
		
		tunningModel = self.model.getModelTuningModel()
		tunningModel.setTuningMode(TuningMode.RANGE)
		tunningModel.setMinValue(freqs[0]/1000.0)
		tunningModel.setMaxValue(freqs[len(freqs)-1]/1000.0)
		tunningModel.setValUnit(UNIT.GHZ)

		#eup
		self.model.getThresholdModel().setThresEupMin(eup[0])
		self.model.getThresholdModel().setThresEupMax(eup[1])

		#aij
		self.model.getThresholdModel().setThresAijMin(aijMin)

		#Quantum number threshold (jup, kup, lup, mup)
		qntm = QuantumNumberThresholdModel()
		qntm.setJupMin(str(jup[0]))
		qntm.setJupMax(str(jup[1]))
		qntm.setKupMin(str(kup[0]))
		qntm.setKupMax(str(kup[1]))
		qntm.setLupMin(str(lup[0]))
		qntm.setLupMax(str(lup[1]))
		qntm.setMupMin(str(mup[0]))
		qntm.setMupMax(str(mup[1]))
		self.model.getThresholdModel().setQntm(qntm)
		
		#noise rmse
		self.model.getNoiseModel().setNoise(rms)		
		
		#components
		continuumCompo = self.model.getEmAbTabbedPanelModel().addContinuumComponent(True)
		if isinstance(continuum, float) or isinstance(continuum, int):
			continuumCompo.setConstantContinuum(float(continuum))
			continuumCompo.getContinuumModel().setSelectedContinuum(ContinuumParameters.DEFAULT_0)
		else :
			continuumCompo.setConstantContinuum(0.0)
			continuumCompo.getContinuumModel().setSelectedContinuum(continuum)
		
		num_compo_species = 1
		for com in components:
			#get the current component with the default values
			comDesc = self.model.getEmAbTabbedPanelModel().addNewComponent()
			comDesc.setComponentName("Component %d" % num_compo_species)
			num_compo_species = num_compo_species +1

			# Geometry for the component
			if com[ScriptConstants.RADEX_COMPONENT_GEOMETRY].lower() == "sphere":
				comDesc.setGeometryMode(ComponentMode.SPHERE_MODE)
			elif com[ScriptConstants.RADEX_COMPONENT_GEOMETRY].lower() == "expanding sphere":
				comDesc.setGeometryMode(ComponentMode.EXPANDING_SPHERE_MODE)
			else:
				comDesc.setGeometryMode(ComponentMode.SLAB_MODE)

			#modify the component attributes
			if com[ScriptConstants.RADEX_COMPONENT_MODEL].lower()=="lteradex":
				comDesc.setLteRadexMode(True)
			elif com[ScriptConstants.RADEX_COMPONENT_MODEL].lower()=="radex":
				comDesc.setFullRadexMode(True)
			else:
				comDesc.setFullLteMode(True)
			comDesc.setDensity(com[ScriptConstants.RADEX_COMPONENT_DENSITY]) #n
			comDesc.setVlsr(com[ScriptConstants.RADEX_COMPONENT_VLSR]) #vlsr
			comDesc.setInteracting(com[ScriptConstants.RADEX_COMPONENT_INTERACTING])#interacting
			moleculeList = ArrayList()

			for mol in com[ScriptConstants.RADEX_COMPONENT_MOLECULES]: #molecules
				radexMolDesc = MoleculeDescription()
				radexMolDesc.setName(mol[ScriptConstants.RADEX_MOLECULE_NAME])
				radexMolDesc.setDataSource(mol[ScriptConstants.RADEX_MOLECULE_DATABASE])
				radexMolDesc.setSourceSize(mol[ScriptConstants.RADEX_MOLECULE_SIZE])
				radexMolDesc.setSpeciesId(str(mol[ScriptConstants.RADEX_MOLECULE_TAG]))
				radexMolDesc.setTemperature(mol[ScriptConstants.RADEX_MOLECULE_TEX])
				radexMolDesc.setDensity(mol[ScriptConstants.RADEX_MOLECULE_NMOL])
				radexMolDesc.setVelocityDispersion(mol[ScriptConstants.RADEX_MOLECULE_FWHM])
				radexMolDesc.setTKin(mol[ScriptConstants.RADEX_MOLECULE_TKIN])
				radexMolDesc.setCollision(mol[ScriptConstants.RADEX_MOLECULE_COLLISION])
				radexMolDesc.setCompute(True)
				moleculeList.add(radexMolDesc)	
			comDesc.getCassisTableMoleculeModel().setList(moleculeList)
			mol = moleculeList.get(0)
			if not (ScriptConstants.RADEX_COMPONENT_TEX in com):
				comDesc.setTex(mol.getTemperature())
			else:
				comDesc.setTex(com[ScriptConstants.RADEX_COMPONENT_TEX])
			if not (ScriptConstants.RADEX_COMPONENT_TKIN in com):
				comDesc.setTkin(mol.getTKin())
			else:
				comDesc.setTex(com[ScriptConstants.RADEX_COMPONENT_TKIN])
			if not (ScriptConstants.RADEX_COMPONENT_SIZE in com):
				comDesc.setSize(mol.getSourceSize())
			else:
				comDesc.setSize(com[ScriptConstants.RADEX_COMPONENT_SIZE])
			#warning
			if self.choice == None:
				if warning == False:
					self.choice = JOptionPane.YES_NO_OPTION;

		self.control = LteRadexControl(self.model, None)
		self.check_parameters = self.control.checkParameters()
		if (self.check_parameters):
			server = ServerImpl()
			comp = self.model.getEmAbTabbedPanelModel().getComponentList()
	
			params = self.model.getMapParameter()
			#params.put("lineAnalysis", ParameterDescription(1.))
			params.put("noCompression", ParameterDescription(1.))
			params.put("script", ParameterDescription(1.))
			params.put("line_freq", ParameterDescription(lineFrequency))
			params.put("freqMin", ParameterDescription(freqs[0]))
			params.put("freqMax", ParameterDescription(freqs[len(freqs)-1]))
			params.put("vlsrOffset", ParameterDescription(vlsrOffset))
			continuum_param = ParameterDescription()
			continuum_param.setVarName(str(continuum))
			params.put("continuum",continuum_param)
			
			self.result = server.computeLteRadexSpectrum(params, 
				freqs, self.model.getEmAbTabbedPanelModel().getComponentList(),
				self.model.getParametersModel().getTelescope())
			self.control.setResult(self.result)
		else :
			self.result = None
		return self.result

	#========================================
	# output the result to 'dir'
	def output(self, dir, prefix, index):
		self.choice = ScriptUtilities.checkExist(dir, self.choice)

		if self.choice == JOptionPane.NO_OPTION or self.choice == JOptionPane.CLOSED_OPTION:
			self.filename = dir + File.separator + prefix + str(index)
			while True:
				if File(self.filename + '.votable').exists():
					self.filename = self.filename + '_1'
				else:
					break;
			self.filename += '.votable'
		else:
			self.filename = dir + File.separator + prefix + str(index) + '.votable'
		print(self.filename)

		file = File(self.filename)
		saver = FileManagerVOTable(file)
		saver.save(file , self.result)
		return


	#========================================
	# plot the result
	def plot(self):
		panel =  LteRadexPanel(self.control)
		PanelView.getInstance().addLteRadexView(panel, False)

		frameName = "LTE + RADEX "
		cassisModel = CassisModel(self.result, self.model)
		event = CassisTableDisplayEvent(panel, cassisModel, self.model, frameName)
		if self.result != None and self.result != [] and len(self.result.getListOfLines()) > 0:
			self.control.getListeners().fireCassisTableDisplayListener(event)
		return


	#========================================
	# make a config file
	def makeConfig(self, configname):
		self.model.makeConfig(configname, self.filename)
		return
