package com.ejie.ab78.utilities.utils;

import java.util.HashSet;
import java.util.Set;

import javax.xml.namespace.QName;
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.w3c.dom.Document;

import com.ejie.ab78.comun.Constantes;

import n38a.exe.N38APISesion;

public class N38TokenClientHandler implements SOAPHandler<SOAPMessageContext> {
	private static final Logger logger = LoggerFactory.getLogger(N38TokenClientHandler.class);
	private TransformerFactory transformerFactory;

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

	public Set<QName> getHeaders() {
		return new HashSet<QName>();
	}

	public void close(MessageContext context) {
		// Nada que hacer
	}

	public boolean handleFault(SOAPMessageContext context) {
		return true;
	}

	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 {

				// crear token n38 de aplicacion
				Document token = this.obtenerTokenDocument();

				// recuperar cabecera SOAP
				SOAPHeader soapHeader = context.getMessage().getSOAPHeader();

				// incluir token en la cabecera creada
				Source source = new DOMSource(token);
				Result result = new DOMResult(soapHeader);
				this.transformerFactory.newTransformer().transform(source, result);

				// se puede continuar el procesamiento
				valid = true;
			} catch (Exception e) {
				N38TokenClientHandler.logger.error(e.getMessage());
			}
		}
		return valid;
	}

	private Document obtenerTokenDocument() throws Exception {
		Document documento = null;

		/*
		 * INICIO DESARROLLO
		 */
		try {
			N38APISesion miApiSesion = new N38APISesion();
			documento = miApiSesion.n38APISesionCrearApp(Constantes.CODIGO_APLICACION);
		} catch (Exception e) {
			N38TokenClientHandler.logger
					.error("Se ha producido un error al obtener el token de aplicación. ERROR: " + e);
			throw new Exception("ERROR: Se ha producido un error al obtener el token de aplicación.", e);
		}
		/* FIN DESARROLLO */

		return documento;
	}
}
