package lu.tudor.santec.gecamed.esante.utils;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;

/**
 * 
 * @author donak
 * 
 * @version <br>
 *          $Log: Utility.java,v $
 *          Revision 1.3  2014-02-05 07:04:12  ferring
 *          write upload string as UTF-8
 *
 *          Revision 1.2  2013-10-21 08:19:24  ferring
 *          CDA opening improved
 *
 *          Revision 1.1  2013-10-07 16:12:12  donak
 *          Logging, message backup, and error protocol creation
 *
 * 
 */
public class Utility {

	private static Logger logger = Logger.getLogger(Utility.class.getName());
	
	private static final String	DEFAULT_EXTENSION	= "txt";
	
	private static Map<String, String> mediaTypeExtensionMap;

	/**
	 * Stores the content of a DOM node or DOM-Document to the file-system and
	 * prints a message on screen
	 * 
	 * @param element
	 *            An object of either types: org.w3c.dom.Document,
	 *            javax.xml.soap.SOAPMessage, org.w3c.dom.Node, or
	 *            java.lang.String
	 * @param message (OPTIONAL)
	 *            An output message that will be printed on screen followed by
	 *            an indication of the save path. Null omits the output message.
	 * @param path
	 *            The path to which the content should be saved
	 * @param fileName
	 *            The filename of the file
	 */
	public static void debugSaveContent(Object element, String message, String path, String fileName) {

		String fullPath = path + "\\" + fileName;
		try {

			// if a message has been enabled, write it to the logfile
			if (message != null) {
				logger.info(message + " \"" + fullPath + "\"");
			}

			// extract the content of the provided object
			String content = Utility.getObjectContent(element);

			// and write it to disk
			PrintWriter debugWriter = new PrintWriter(fullPath);
			debugWriter.print(content);
			debugWriter.flush();
			debugWriter.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			logger.warn("Unable to write content to \"" + fullPath + "\"", e);
		}

	}

	/**
	 * Extracts the content of a SOAP message, DOM-Document or DOM node
	 * 
	 * @param object
	 *            An object of either types: org.w3c.dom.Document,
	 *            javax.xml.soap.SOAPMessage, org.w3c.dom.Node, or
	 *            java.lang.String (whereas in case of a string this string will
	 *            simply be returned)
	 * @return The content of the provided object as string
	 */
	public static String getObjectContent(Object object) throws Exception {
		String output = null;
		if (object instanceof org.w3c.dom.Document) {
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer transformer = tf.newTransformer();
			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
			StringWriter writer = new StringWriter();
			transformer.transform(new DOMSource((org.w3c.dom.Document) object), new StreamResult(writer));
			output = writer.getBuffer().toString();
		} else if (object instanceof javax.xml.soap.SOAPMessage) {
			StringBuffer sbuf = new StringBuffer();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			((javax.xml.soap.SOAPMessage) object).writeTo(baos);
			sbuf.append(baos.toString("UTF-8"));
			output = sbuf.toString();
		} else if (object instanceof org.w3c.dom.Node) {
			DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
			DOMImplementationLS lsImpl = (DOMImplementationLS) registry.getDOMImplementation("LS");
			LSSerializer serializer = lsImpl.createLSSerializer();
			output = serializer.writeToString((org.w3c.dom.Node) object);
		} else if (object instanceof String) {
			output = (String) object;
		} else {
			throw new Exception("Sorry, object type \"" + object.getClass().getName() + "\" is currently not supported.");
		}

		return output;
	}

	public static String getExtensionForMediaType (String mediaType)
	{
		String extension;
		String[] info;
		
		if (mediaType == null)
			return null;
		
		initExtensionForMediaTypeMap();
		
		extension = mediaTypeExtensionMap.get(mediaType);
		if (extension != null)
			return extension;
		
		info = mediaType.split("/");
		if (info.length == 2)
		{
			extension = mediaTypeExtensionMap.get(info[1]);
			if (extension != null)
				return extension;
			
			extension = mediaTypeExtensionMap.get(info[0]);
			if (extension != null)
				return extension;
			
			if ("application".equals(info[0]))
				return info[1];
		}
		
		return DEFAULT_EXTENSION;
	}
	
	
	private static void initExtensionForMediaTypeMap ()
	{
		if (mediaTypeExtensionMap == null)
		{
			// create and fill the map
			
			mediaTypeExtensionMap = new HashMap<String, String>();
			
//			mediaTypeExtensionMap.put("application/pdf", "pdf");
//			mediaTypeExtensionMap.put("text/x-hl7-text+xml", "xml");
		}
	}
}
