/* ========================
 * JSynoptic : a free Synoptic editor
 * ========================
 *
 * Project Info:  http://jsynoptic.sourceforge.net/index.html
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * (C) Copyright 2001-2003, by :
 *     Corporate: 
 *         Astrium SAS 
 *         EADS CRC
 *     Individual: 
 * 		   Christophe Pecquerie
 *         updated for SMI (especially for GHYPS) by Mathias Choquet
 *
 * $Id: TspDataPlugin.java,v 1.5 2005/09/14 16:18:05 erk Exp $
 * 
 * Changes ------- 06-Jan-2004 : Creation Date (NB);
 *  
 */
package tsp.consumer.plugin.jsynopticSMI;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

import jsynoptic.base.Plugin;
import jsynoptic.ui.JSynoptic;
import simtools.data.DataInfo;
import simtools.data.DataSource;
import simtools.data.DataSourceCollection;
import simtools.data.DataSourcePool;
import simtools.data.DataSourceProvider;
import simtools.data.DuplicateIdException;
import tsp.consumer.plugin.jsynopticSMI.impl.TspHandler;
import tsp.consumer.plugin.jsynopticSMI.impl.TspHandler.TspProviderNotFoundException;
import tsp.consumer.plugin.jsynopticSMI.ui.TspDialogOpenProvider;
import tsp.core.common.url.TspMalformedURLException;
import tsp.core.common.url.TspNoServerFoundException;
import tsp.core.common.url.TspURL;
import tsp.core.common.url.TspURLFactory;
import tsp.core.common.url.TspUnknownHostException;
import tsp.core.common.url.TspUnknownServerNameException;
import tsp.core.common.url.TspUnknownServerNumberException;
import tsp.core.rpc.TSP_sample_symbol_info_t;

public final class TspDataPlugin extends Plugin implements DataSourceProvider, ActionListener {
	TspDataSourceCollection tdsc;
	protected JMenuItem jmi;
	protected String statusMessage;
	TspHandler tspHandler;
	
	public void setStatusMessages(String s){
		statusMessage = s;
	}
	
	public String getStatusMessages(){
		return statusMessage;
	}
	
	public TspDataPlugin() {
		DataSourcePool.global.addProvider(this);
	}
	
	/**
	 * this method carries out an in-house connection TSP 
	 * (from another plugin, for example)
	 */
	//TODO add argument to the method in order to Inform the provider about 
	//the frequency and the other informations about the TSP connection
	public boolean intraPluginConnection(String uRL){
		boolean connectionOK = false; 
		try {
			TspURL url = TspURLFactory.createWithDefaultSupport(uRL);				
			tspHandler = new TspHandler(url);
			tspHandler.setSamplingPhase(0);
			tspHandler.setPeriod_(32);
			tdsc = new TspDataSourceCollection(tspHandler);
			DataSourcePool.global.addDataSourceCollection(tdsc);
			setStatusMessages("Connected to " + url );
			connectionOK = true;
			
		} catch (TspMalformedURLException e) {
			setStatusMessages("Malformed URL");
			tspHandler = null;
			connectionOK = false;
		} catch (TspUnknownHostException e) {				
			setStatusMessages("Unknown Host");
			tspHandler = null;
			connectionOK = false;
		} catch (TspUnknownServerNameException e) {				
			setStatusMessages("Unknown ServerName");
			tspHandler = null;
			connectionOK = false;
		} catch (TspUnknownServerNumberException e) {				
			setStatusMessages("Unknown ServerNumber");
			tspHandler = null;
			connectionOK = false;
		} catch (TspNoServerFoundException e) {				
			setStatusMessages("No server found on host");
			tspHandler = null;	
			connectionOK = false;
		} catch (TspProviderNotFoundException e) {
			setStatusMessages("No TSP provider found on this host");
			tspHandler = null;
			connectionOK = false;
		} catch (Exception e) {
			setStatusMessages(e.getMessage());
			tspHandler = null;
			connectionOK = false;
		}
		return connectionOK;
	}
	
	/** 
	 * Adds a menu entry in the file menu
	 */
	public void setMenu(JMenuBar mb) {
		Component c[] = mb.getComponents();
		for (int i=0; i<c.length; ++i) {
			JMenu jm = (JMenu)c[i];
			/*Search for the file menu*/
			if (jm.getText().equals(JSynoptic.resources.getString("fileMenu"))) {
				
				Component cm[] = jm.getMenuComponents();
				for (int j=0; j<cm.length; ++j) {
					JMenuItem jsm = (JMenuItem)cm[j];
					/*Search for the menu item "open"*/
					if (jsm.getText().equals(JSynoptic.resources.getString("openMenu"))) {
						jmi = new JMenuItem("Open TSP Provider (SMI)...");
						jm.add(jmi,2);
						jmi.addActionListener(this);
					}
				}
			}
		}
		
	}
	
	
	/**
	 * Returns the plugin information
	 */
	public String about() {
		return "TSP sources (SMI compliant), a TSP consumer plugin by Mathias Choquet";
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent arg0) {
		//Open dialog to connect to a new Tsp provider
		TspDialogOpenProvider windowOpenProvider = new TspDialogOpenProvider();
		
		tspHandler = windowOpenProvider.getTspHandler();
		if (tspHandler != null)
		{
			//Create data sources collection
			tdsc = new TspDataSourceCollection(tspHandler);
			DataSourcePool.global.addDataSourceCollection(tdsc);
		}
	}
	
	/* (non-Javadoc)
	 * @see simtools.data.DataSourceProvider#getOptionalInformation(simtools.data.DataSource, simtools.data.DataSourceCollection)
	 */
	public Object getOptionalInformation(DataSource ds, DataSourceCollection dsc) {
		if ((dsc==null) || (!(dsc instanceof TspDataSourceCollection)))
			return null;
		
		tdsc = (TspDataSourceCollection) dsc;
		
		// As we have only random sources, we can easily re-create those.
		// Just storing the number of sources we have is enough
		return tdsc.tspHandler_;
	}
	
	/* (non-Javadoc)
	 * @see simtools.data.DataSourceProvider#provide(java.lang.String, java.lang.String, java.lang.Object, simtools.data.DataSourcePool)
	 */
	public DataSource provide(String id, String dscId, Object optionalInformation, DataSourcePool pool) {
		// Ignore requests that are not for this object
		if ((dscId==null) || (!dscId.startsWith("TSP"))) return null;
		
		// Usually, a provider may not need the pool  
		// In this example, we suppose there is only one instance, and that it was put in the
		// pool by this plugin. So, if the pool is not the global one, error
		if (pool!=DataSourcePool.global) return null;
		
		// Get the unique instance
		
		try {
			//Get the optional information provided by the deserialization
			TspHandler tspHandler = (TspHandler)optionalInformation;
			//Get the corresponding collection
			tdsc = (TspDataSourceCollection)pool.getDataSourceCollectionWithId(tspHandler.getId());
			if (tdsc == null) {				
				TspDialogOpenProvider windowOpenProvider = new TspDialogOpenProvider(tspHandler);
				tspHandler = windowOpenProvider.getTspHandler();
				
				if(tspHandler == null)	return null;
				
				tdsc = new TspDataSourceCollection(tspHandler);
				DataSourcePool.global.addDataSourceCollection(tdsc);
			}
			//Find the source in tspHandler's symbols list
			for(int i=0; i<tdsc.tspHandler_.getSymbolTab().length ; i++)
				if(tdsc.tspHandler_.getSymbolTab()[i].name.equals(id)) {
					TSP_sample_symbol_info_t symbol = tdsc.tspHandler_.getSymbolTab()[i];
					tdsc.addSource(new DataInfo(symbol.name,symbol.name,"Symbol from " + tdsc.tspHandler_.getUrl().getHost() + ":" + tdsc.tspHandler_.getProviderChannelId(),"NA"));
					break;
				}
				// Now we're confident all sources were re-created, so return the source for this id
			return tdsc.get(id);
		} catch (DuplicateIdException e) {
			e.printStackTrace();
			return null;
		}
	}
	/*
	 * method for simulation commanding
	 */
	//TODO improve the commanding of simulation by using TSP_WRITE
	public void run(){
		tdsc.run();
	}
	
	/**
	 * method for simulation commanding
	 */
	//TODO improve the commanding of simulation by using TSP_WRITE
	public void pause(){
		tdsc.run();
	} 
}
