package com.ejie.w43df.pid.header;

import java.io.ByteArrayInputStream;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPHeader;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.w3c.dom.Document;

public class W43dfHeaderHandler implements SOAPHandler<SOAPMessageContext> {

	private static final String XML_VERSION_ENCODING = "<?xml version='1.0' encoding='ISO-8859-1'?>";
	private static final String IDENTITY_HEADER_NAMESPACE_URI = "com/ejie/documents/xml";
	private static final String IDENTITY_HEADER_NAMESPACE_PREFIX = "pidns";
	private static final String IDENTITY_HEADER_LOCAL_PART = "W43sIdentity";

	private TransformerFactory transformerFactory;
	private String securityToken = null;

	public W43dfHeaderHandler(String securityToken) throws Exception {
		this.securityToken = securityToken;
		this.transformerFactory = TransformerFactory.newInstance();
		if (securityToken != null && !securityToken.isEmpty()) {
			this.securityToken = securityToken.replaceAll(XML_VERSION_ENCODING,
					"");
		} else {
			throw new Exception(
					"Error: security token cannot be null or empty.");
		}
	}

	public boolean handleMessage(SOAPMessageContext context) {
		boolean bValid = false;
		Boolean outboundProperty = (Boolean) context
				.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
		if (outboundProperty.booleanValue()) {
			try {
				DocumentBuilder docBuilder = DocumentBuilderFactory
						.newInstance().newDocumentBuilder();
				Document token = docBuilder.parse(new ByteArrayInputStream(
						securityToken.getBytes()));
				// Recuperar cabecera SOAP
				SOAPHeader soapHeader = context.getMessage().getSOAPHeader();
				// Anyadir un child element de tipo w43sIdentity. Es necesario
				// ya que el elemento debe tener namespace, y si se inserta
				// directamente el XML de N38 no tiene namespace.
				SOAPElement soapElement = soapHeader.addChildElement(new QName(
						IDENTITY_HEADER_NAMESPACE_URI,
						IDENTITY_HEADER_LOCAL_PART,
						IDENTITY_HEADER_NAMESPACE_PREFIX));
				// En SOAP 1.2 la cabecera debe tener namespace
				// Incluir token en la cabecera creada
				Source source = new DOMSource(token);
				Result result = new DOMResult(soapElement);

				this.transformerFactory.newTransformer().transform(source,
						result);

				bValid = true;
			} catch (Exception e) {
				e.printStackTrace();
				bValid = false;
			}
		} else {
			// Nothing to do..
			bValid = false;
		}
		return bValid;

	}

	/*
	 * public boolean handleMessage(SOAPMessageContext context) { boolean bValid
	 * = false; Boolean outboundProperty = (Boolean)
	 * context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if
	 * (outboundProperty.booleanValue()) { try { DocumentBuilder docBuilder =
	 * DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document token
	 * = docBuilder.parse(new ByteArrayInputStream(securityToken.getBytes()));
	 * // Recuperar cabecera SOAP SOAPHeader soapHeader =
	 * context.getMessage().getSOAPHeader(); // En SOAP 1.2 la cabecera debe
	 * tener namespace // Incluir token en la cabecera creada Source source =
	 * new DOMSource(token); Result result = new DOMResult(soapHeader);
	 * 
	 * this.transformerFactory.newTransformer().transform(source, result);
	 * soapHeader. bValid = true; } catch (Exception e) { e.printStackTrace();
	 * bValid = false; } } else { // Nothing to do.. bValid = false; } return
	 * bValid;
	 * 
	 * }
	 */

	public Set<QName> getHeaders() {
		// throw new UnsupportedOperationException("Not supported yet.");
		return null;
	}

	public boolean handleFault(SOAPMessageContext context) {
		// throw new UnsupportedOperationException("Not supported yet.");
		return true;
	}

	public void close(MessageContext context) {
		// throw new UnsupportedOperationException("Not supported yet.");
	}
}
