package samples.applets;

import java.applet.Applet;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.InputStream;
import java.net.URL;

import de.fmui.spheon.jsoap.Envelope;
import de.fmui.spheon.jsoap.Fault;
import de.fmui.spheon.jsoap.ParamBag;
import de.fmui.spheon.jsoap.RPCCall;
import de.fmui.spheon.jsoap.SoapConfig;
import de.fmui.spheon.jsoap.transport.http.SoapHttpClient;

/**
 * @author Theo
 */
public class SampleChemistryApplet extends Applet implements ActionListener
{
	private Label			endpointLabel;
	private TextField		endpointField;

	private CheckboxGroup	numerOrSymboleGroup;
	private Checkbox		numberBox;
	private TextField		numberField;
	private Checkbox		symbolBox;
	private TextField		symbolField;

	private Button			connectButton;
	private TextArea		resultArea;
	
	private SoapConfig 		sc;
	private String 			endpointURL;
	
	/**
	 * Inits the applet.
	 */
	public void init() 
	{
		// set default endpoint
		endpointURL = getParameter("endpoint");
		if(endpointURL == null) { endpointURL = "";	}
		
		// get SOAP configuration
		sc = new SoapConfig();
		loadJSOAPConfig(sc);
		
		// add the chemistry type
		SoapConfig.Xsd xsd = sc.addNamespace("http://spheon.bov.de");
		sc.addStructType(xsd, "ChemistryElement", "samples.applets.ChemistryElement");

		// draw some widgets
		setupUI();
	}

	/**
	 * This is just for old Netscape 4.x browsers, that not allow to
	 * read data files from a jar file ....
	 */
	private void loadJSOAPConfig(SoapConfig sc)
	{
		// check, if the configuration file is already loaded
		if(!sc.getXsdMap().isEmpty()) { 
			return; 
		}
		
		// Ok, it's an old browser.
		// Load the configuration file from URL.
		try {
			URL configUrl = new URL(getDocumentBase(), "jsoapconfig.xml");
			
			InputStream configStream = configUrl.openStream();
			sc.addToConfig(configStream);
			configStream.close();
		}
		catch(Exception e) {
			System.err.println("Cannot load Spheon JSOAP config: " + e);
		}
	}

	/**
	 * Sets up the user interface.
	 */
	private void setupUI()
	{
		GridBagLayout gridbag = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		c.insets = new Insets(5, 5, 5, 5);
		
		setLayout(gridbag);
		
		
		endpointLabel = new Label("SOAP Endpoint:");
		c.gridx = 0;
		c.gridy = 0;
		c.anchor = GridBagConstraints.WEST;
		gridbag.setConstraints(endpointLabel, c);		
		add(endpointLabel);
		
		endpointField = new TextField(endpointURL, 40);
		c.gridx = 1;
		c.gridy = 0;
		c.anchor = GridBagConstraints.WEST;		
		gridbag.setConstraints(endpointField, c);
		add(endpointField);
		
		connectButton = new Button("Connect");
		c.gridx = 2;
		c.gridy = 0;
		c.anchor = GridBagConstraints.WEST;		
		gridbag.setConstraints(connectButton, c);
		connectButton.addActionListener(this);		
		add(connectButton);
				
		
		numerOrSymboleGroup = new CheckboxGroup();
		numberBox = new Checkbox("Atomic number:", numerOrSymboleGroup, true);
		symbolBox = new Checkbox("Symbol:", numerOrSymboleGroup, false);
		

		c.gridx = 0;
		c.gridy = 1;
		c.anchor = GridBagConstraints.WEST;
		gridbag.setConstraints(numberBox, c);
		add(numberBox);

		numberField = new TextField(3);
		c.gridx = 1;
		c.gridy = 1;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.anchor = GridBagConstraints.WEST;		
		gridbag.setConstraints(numberField, c);
		add(numberField);


		c.gridx = 0;
		c.gridy = 2;
		c.anchor = GridBagConstraints.WEST;
		gridbag.setConstraints(symbolBox, c);
		add(symbolBox);

		symbolField = new TextField(3);
		c.gridx = 1;
		c.gridy = 2;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.anchor = GridBagConstraints.WEST;		
		gridbag.setConstraints(symbolField, c);
		add(symbolField);


		resultArea = new TextArea("", 10, 80, TextArea.SCROLLBARS_NONE);
		resultArea.setEditable(false);
		resultArea.setFont(new Font("Courier", Font.PLAIN, 11));
		
		c.gridx = 0;
		c.gridy = 3;
		c.gridheight = 10;
		c.anchor = GridBagConstraints.WEST;
		gridbag.setConstraints(resultArea, c);	
		
		add(resultArea);
	}

	/**
	 * Handles UI actions.
	 */
	public void actionPerformed(ActionEvent e) 
	{
		if(e.getSource() == connectButton) {
			startCall();
		}
	}
	
	/**
	 * Prepears the call and handles the result.
	 */
	private void startCall()
	{
		String result = null;
			
		try {
			String input;	
			boolean numberOrSymbol = (numerOrSymboleGroup.getSelectedCheckbox() == numberBox);
			
			if(numberOrSymbol)	{ input = numberField.getText(); }
			else				{ input = symbolField.getText(); }
				
			result = executeCall(endpointURL, numberOrSymbol, input);
		}
		catch(Exception ex) {
			ex.printStackTrace();
			result = ex.toString();
		}
			
		resultArea.setText(result);		
	}
	
	/**
	 * Executes the SOAP call and returns a String.
	 * 
	 * @param endpoint the URL of the webservice 
	 * @param numberOrSymbol <code>true</code>: number, <code>false</code>: symbol 
	 * @param input number (as String) or symbol
	 * @return a formated result string 
	 */
	private String executeCall(String endpoint, boolean numberOrSymbol, String input)
		throws Exception
	{
		String result = "Result:\n-------\n\n";
		
		String method;
		if(numberOrSymbol)	{ method = "getElementByNumber"; }
		else				{ method = "getElementBySymbol"; }
		
		// prepare a call
		RPCCall call = new RPCCall(sc, "urn:SpheonJSOAPChemistry", method);

		// set parameter
		if(numberOrSymbol)	{ call.setParameter("number", new Integer(input), int.class); } 
		else 				{ call.setParameter("symbol", input, String.class); }

		// execute call (via HTTP)
		SoapHttpClient shc = new SoapHttpClient(sc);
		Envelope answer = shc.invokeHTTP(new URL(endpoint), "", call.getEnvelope()); 
			
		// check for a fault message
		if(answer.hasFault()) {			
			Fault f = answer.getFault();
			
			// build a result string
			result += "Faultcode:   " + f.getFaultcode() + "\n";
			result += "Faultstring: " + f.getFaultstring() + "\n";
			result += "Faultactor:  " + f.getFaultactor() + "\n";
				
			return result;
		}
	
		// get the result
		ParamBag p = call.getResults(answer);
		ChemistryElement ce = (ChemistryElement) p.getValue(0);
		
		// build a result string
		result += "Atomic number: " + ce.atomicnumber + "\n";
		result += "Symbol:        " + ce.symbol + "\n";
		result += "Name:          " + ce.name + "\n";
		result += "Mass:          " + ce.mass + "\n";
		result += "Melting point: " + ce.meltingPoint + " K\n";			
		result += "Boiling point: " + ce.boilingPoint + " K\n";			
		result += "Found:         " + ce.found + "\n";
										
		return  result;		
	}

	/**
	 * Returns applet infos.
	 */
	public String getAppletInfo() 
	{
		return "Spheon JSOAP applet sample: SampleChemistryApplet\nhttp://soap.fmui.de/";
	}
	
	/**
	 * Returns parameter infos.
	 */
	public String[][] getParameterInfo() 
	{
		return new String[][] { { "endpoint", "URL", "SOAP endpoint" } };
	}
}
