package org.omg.lsae.notifications;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.biomoby.shared.MobyException;
import org.omg.lsae.sax.EventParser;
import org.w3c.dom.Document;

/**
 * This class represent the base LSAE Notification Event.
 * 
 * ------------ TODO -> should this really be abstract? Spec might allow for
 * instantiation of this class ------------
 * 
 * @author Eddie
 * 
 */
public abstract class AnalysisEvent {

	// the event message
	private String message = "";

	// the events timestamp
	private String timestamp = "";

	// the id
	private String queryId = "";

	/**
	 * Default Constructor
	 * 
	 */
	public AnalysisEvent() {
		this.message = "";
		this.timestamp = "";
		this.queryId = "";
	}

	/**
	 * 
	 * @param msg the event message to set
	 */
	public void setMessage(String msg) {
		if (msg == null)
			msg = "";
		this.message = msg;
	}

	/**
	 * 
	 * @return the event message
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * 
	 * @param id the queryId to set
	 */
	public void setQueryId(String id) {
		if (id == null)
			id = "";
		this.queryId = id;
	}

	/**
	 * 
	 * @return the events queryId
	 */
	public String getQueryId() {
		return queryId;
	}

	/**
	 * TODO - is there a specific format?
	 * @param time the events timestamp
	 */
	public void setTimestamp(String time) {
		if (time == null)
			time = "";
		this.timestamp = time;
	}

	/**
	 * 
	 * @return the events timestamp
	 */
	public String getTimestamp() {
		return timestamp;
	}

	/**
	 * TODO - the whole toXML may be un-necessary. Currently, it isnt even used...
	 * @return a Document to be used for manipulation
	 */
	protected Document createDomDocument() {
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			factory.setNamespaceAware(true);
			factory.setValidating(true);
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.newDocument();
			return doc;
		} catch (ParserConfigurationException e) {
		}
		return null;
	}

	/**
	 * Style sheet to output formatted XML
	 */
	protected final String XSLT = "<!DOCTYPE stylesheet [\r\n"
			+ "  <!ENTITY cr \"<xsl:text>\r\n"
			+ "</xsl:text>\">\r\n"
			+ "]>\r\n"
			+ " \r\n"
			+ "<xsl:stylesheet\r\n"
			+ "    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" \r\n"
			+ "    xmlns:xalan=\"http://xml.apache.org/xslt\" \r\n"
			+ "    version=\"1.0\">\r\n"
			+ "    \r\n"
			+ "    <xsl:output method=\"xml\" indent=\"yes\" xalan:indent-amount=\"4\"/> \r\n"
			+ "      \r\n"
			+ "    <!-- copy out the xml -->\r\n"
			+ "    <xsl:template match=\"* | @*\">\r\n"
			+ "        <xsl:copy><xsl:copy-of select=\"@*\"/><xsl:apply-templates/></xsl:copy>\r\n"
			+ "    </xsl:template>\r\n" + " \r\n" + "</xsl:stylesheet>";

	/**
	 * 
	 * @return true if the event is completed, false otherwise.
	 */
	public abstract boolean isCompleted();

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public abstract String toString();

	/**
	 * 
	 * @return the XML representation of this LSAE notification event object.
	 */
	public abstract String toXMLString();

	/**
	 * 
	 * @param xmlData the xml to parse into an AnalysisEvent object
	 * @return an array of AnalysisEvent objects
	 * @throws MobyException if there is a problem parsing the xml
	 */
	public static AnalysisEvent[] createFromXML(Object xmlData)
			throws MobyException {

		EventParser parser = new EventParser();
		if (xmlData instanceof byte[]) {
			return parser.parse(new ByteArrayInputStream((byte[]) xmlData));
		} else if (xmlData instanceof File) {
			try {
				return parser.parse(new FileInputStream((File) xmlData));
			} catch (IOException e) {
				throw new MobyException(e.toString());
			}
		} else if (xmlData instanceof String) {
			return parser.parse(new StringReader((String) xmlData));
		} else
			throw new MobyException(
					"The Analyisis event  data should be sent/received either as type String or base64/byte[]. But they are of type '"
							+ xmlData.getClass().getName() + "'.");
	}
}
