package com.ejie.ab61.tramita.services;

import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.HashSet;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;

import com.ejie.ab61.comun.utilidades.XlnetsUtils;

/**
 * The Class PidServiceHandler.
 * 
 *  
 */
public class PidServiceHandler implements SOAPHandler<SOAPMessageContext> {

	/** The Constant logger. */
	private static final Logger logger = LoggerFactory.getLogger(PidServiceHandler.class);

	/** The transformer factory. */
	private TransformerFactory transformerFactory;

	/**
	 * Constructor por defecto.
	 *
	 */
	public PidServiceHandler() {
		this.transformerFactory = TransformerFactory.newInstance();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.xml.ws.handler.soap.SOAPHandler#getHeaders()
	 */
	@Override
	public Set<QName> getHeaders() {
		return new HashSet<QName>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * javax.xml.ws.handler.Handler#close(javax.xml.ws.handler.MessageContext)
	 */
	@Override
	public void close(MessageContext context) {
		// Metodo vacio
	}

	/**
	 * Handle fault.
	 *
	 * @param context
	 *            the context
	 * @return true, if successful
	 * @see javax.xml.ws.handler.Handler#handleFault(javax.xml.ws.handler.MessageContext)
	 */
	@Override
	public boolean handleFault(SOAPMessageContext context) {
		logger.error("Error cliente ws PID " + logging(context));
		return true;
	}

	/**
	 * Handle message.
	 *
	 * @param context
	 *            the context
	 * @return true, if successful
	 * @see javax.xml.ws.handler.Handler#handleMessage(javax.xml.ws.handler.MessageContext)
	 */
	@Override
	public boolean handleMessage(SOAPMessageContext context) {
		boolean valid = true;
		Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
		// solo para los mensajes SALIENTES
		if (outbound != null && outbound.booleanValue()) {
			valid = false;
			try {
				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
				DocumentBuilder builder = factory.newDocumentBuilder();

				org.w3c.dom.Document token = builder
						.parse(new InputSource(new StringReader(XlnetsUtils.getInstance().getTokenAplicacion(false))));
				// recuperar cabecera SOAP
				SOAPHeader soapHeader = context.getMessage().getSOAPHeader();
				if (soapHeader == null) {
					soapHeader = context.getMessage().getSOAPPart().getEnvelope().addHeader();
				}
				SOAPElement identity = soapHeader.addChildElement(context.getMessage().getSOAPPart().getEnvelope()
						.createName("w43sIdentity", "ns", "com/ejie/documents/xml"));
				// incluir token en la cabecera creada
				Source source = new DOMSource(token);
				Result result = new DOMResult(identity);
				this.transformerFactory.newTransformer().transform(source, result);
				// se puede continuar el procesamiento
				valid = true;
				logger.info("cliente ws PID outbound: Token inyectado al header");
				context.put("timeini", new Long(System.currentTimeMillis()));
			} catch (Exception e) {
				logger.error("Error", e);
			}

		} else {
			long timeini = (Long) (context.get("timeini"));
			long timefin = System.currentTimeMillis();
			BigDecimal result = (new BigDecimal(timefin).subtract(new BigDecimal(timeini))).divide(new BigDecimal(1000),
					5, BigDecimal.ROUND_FLOOR);

			logger.info("cliente ws PID tiempo transcurrido de respuesta: " + result + " sg ");
		}
		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			context.getMessage().writeTo(out);
			String strMsg = out.toString("UTF-8");
			if (outbound != null && outbound.booleanValue()) {
				logger.info("**************** cliente ws PID mensaje enviado: " + strMsg);
			} else {
				logger.info("**************** cliente ws PID mensaje recibido: " + strMsg);
			}
		} catch (Exception e) {
			logger.error("cliente ws PID error al tracear mensaje", e);
		}
		return valid;

	}

	/**
	 * Logging.
	 *
	 * @param context
	 *            the context
	 * @return the string
	 */
	private String logging(SOAPMessageContext context) {
		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			context.getMessage().writeTo(out);
			return new String(out.toByteArray());
		} catch (Exception e) {
			logger.error("Error", e);
		}
		return "NO SACAMOS MENSAJE SOAP";
	}
}
