package com.ejie.ad74a.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.rmi.UnmarshalException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

public class UtilidadesXML {
	/** Constructor privado */
	private UtilidadesXML() {
	}

	private static final Logger logger = LoggerFactory.getLogger(UtilidadesXML.class);

	public static String marshalObjectWS(Object o) throws Exception {
		StringWriter sw = new StringWriter();
		JAXBContext jc = JAXBContext.newInstance(o.getClass());
		Marshaller marshaller = jc.createMarshaller();
		// para que no incluya <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
//		marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", false);
		marshaller.marshal(o, sw);
		return sw.toString();
	}

	public static Object unmarshallerObject(String xml, Class clazz) throws UnmarshalException {
		try {
			JAXBContext jaxbContext;
			jaxbContext = JAXBContext.newInstance(clazz);
			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

			return jaxbUnmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes("UTF-8")));
		} catch (JAXBException e) {
			throw new UnmarshalException("Error de JAXB al traducir el XML", e);
		} catch (UnsupportedEncodingException e) {
			throw new UnmarshalException("Error de codificacion al leer el XML", e);
		}
	}
	
	public static String parseDocument2String(Document doc) {
		StringWriter sw;
		try {
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			sw = new StringWriter();
			StreamResult result = new StreamResult(sw);
			transformer.transform(source, result);
			return sw.toString();
		} catch (TransformerConfigurationException e) {
			UtilidadesXML.logger.error("Se ha producido un error en el metodo parseDocumen2String: " + e.getMessage());
		} catch (TransformerException e) {
			UtilidadesXML.logger.error("Se ha producido un error en el metodo parseDocumen2String: " + e.getMessage());
		}
		return null;
	}
	
	/**
	 * Obtiene un Document a partir de una cadena
	 * 
	 * @param s la cadena
	 * @return Document el document
	 */
	public static Document string2Document(String s) {
		UtilidadesXML.logger.debug("INI string2Document");
		Document tmpX = null;
		DocumentBuilder builder = null;

		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			tmpX = builder.parse(new ByteArrayInputStream(s.getBytes()));
		} catch (Exception e) {
			UtilidadesXML.logger.error("Error al transformar el String a Document", e);
		}
		return tmpX;

	}
	
	/**
	 * Imprimer por consola el mensaje soap
	 * @param message
	 * @throws Exception
	 */
	public static String printFormattedXML(SOAPMessage message) throws Exception	{
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		message.writeTo(bout);
		String xml = bout.toString();

		Source xmlInput = new StreamSource(new StringReader(xml));
		StringWriter stringWriter = new StringWriter();
		StreamResult xmlOutput = new StreamResult(stringWriter);
		TransformerFactory transformerFactory = TransformerFactory.newInstance();
		transformerFactory.setAttribute("indent-number", 5);
		Transformer transformer = transformerFactory.newTransformer();
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
		transformer.transform(xmlInput, xmlOutput);
		String xmlString = xmlOutput.getWriter().toString();
		//Sustituye estos elementos porque no cogía el prefijo ns y es necesario
		xmlString = xmlString.replace("<cabecera>", "<ns:cabecera>").replace("</cabecera>", "</ns:cabecera>").replace("<datosEmision>", "<ns:datosEmision>").replace("</datosEmision>", "</ns:datosEmision>");
		
		logger.info(xmlString);
		
		return xmlString;

		
	}

}