package com.ejie.ab63.tramitacionModule.mdb;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.ejie.ab63.comun.Constantes;
import com.ejie.ab63.model.Establecimiento;
import com.ejie.ab63.service.EstablecimientoService;

import weblogic.apache.xpath.XPathAPI;

/**
 * Message-Driven Bean implementation class for: TramitacionModuleMDB
 */
@MessageDriven(
		activationConfig = { @ActivationConfigProperty(
				propertyName = "destination", propertyValue = "AB63.ab63GestorEventosNotifQueue"), @ActivationConfigProperty(
				propertyName = "destinationType", propertyValue = "javax.jms.Queue")
		}, 
		mappedName = "AB63.ab63GestorEventosNotifQueue")

public class TramitacionModuleMDB implements MessageListener {
	
	
	private static final Log logger = LogFactory.getLog(TramitacionModuleMDB.class);

	// Load the ContextSingleton
	private BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance("classpath:beanRefColasContext.xml");

	// Get hold of the factory to use
	private BeanFactoryReference refBea = this.locator.useBeanFactory("ear.context");

	private BeanFactory factoryBea = this.refBea.getFactory();
		
	/**
	 * @see MessageListener#onMessage(Message)
	 */
	public void onMessage(Message message) {

		try {
			if (message instanceof TextMessage) {

				TramitacionModuleMDB.logger.error("Entra en la cola");
				// SE CASTEA EL TIPO DE MENSAJE DE COLA
				TextMessage textMessage = (TextMessage) message;

				// PROPIEDADES OBLIGATORIAS
				String entidad = textMessage.getStringProperty("EventEntity");
				String sistema = textMessage.getStringProperty("EventWho");
				String tipologia = textMessage.getStringProperty("EventTipology");
				String what = textMessage.getStringProperty("EventWhat");

				// PROPIEDADES QUE DEBERIAN LLEGAR PERO NO SON OBLIGATORIAS
				String correlation = textMessage.getStringProperty("EventCorrelationId");
				
				TramitacionModuleMDB.logger.error("entidad " + entidad);
				TramitacionModuleMDB.logger.error("sistema " + sistema);
				TramitacionModuleMDB.logger.error("tipología " + tipologia);
				TramitacionModuleMDB.logger.error("what " + what);
				TramitacionModuleMDB.logger.error("correlation " + correlation);
				TramitacionModuleMDB.logger.error("text " + textMessage.getText());
				// PROPIEDADES DINAMICAS QUE VIENEN EN EL XML(notificationBody)


				HashMap<String, String> resultadoRecogerDatosCola = this.recogerDatosCola(textMessage.getText());
				
				String codigo = resultadoRecogerDatosCola.get("codigo");
				String signatura = resultadoRecogerDatosCola.get("signatura");
				String urlFichaPortal = resultadoRecogerDatosCola.get("urlFichaPortal");
				
				Establecimiento establecimiento = new Establecimiento();
				TramitacionModuleMDB.logger.error("signatura " + signatura);
				establecimiento.setIdentificadorEstablecimiento(signatura);

				
				//eliminamos la fecha de control para permitir otros eventos posteriormente
				establecimiento.setFechaControlS41(null);

				if (Constantes.TipologiaConfirmacion.ALTA.equalsIgnoreCase(tipologia)
						|| Constantes.TipologiaConfirmacion.MODIFICACION.equalsIgnoreCase(tipologia)) {
					TramitacionModuleMDB.logger.error("urlFichaPortal " + urlFichaPortal);
					establecimiento.setUrlPortalS41(urlFichaPortal);
					TramitacionModuleMDB.logger.error("codigo " + codigo);
					establecimiento.setIdPortalS41(Long.parseLong(codigo));
				}else if (Constantes.TipologiaConfirmacion.BAJA.equalsIgnoreCase(tipologia)) {
					establecimiento.setUrlPortalS41(null);
					establecimiento.setIdPortalS41(null);
				}
				TramitacionModuleMDB.logger.error("UPDATE CAMPOS ");
				
				EstablecimientoService establecimientoService = this.factoryBea.getBean(EstablecimientoService.class);  
				TramitacionModuleMDB.logger.error("establecimientoService ");
				establecimientoService.updateCamposS41(establecimiento);

			} else {
				TramitacionModuleMDB.logger.error("Tipo de mensaje JMS invalido");
			}
		} catch (Exception e) {
			TramitacionModuleMDB.logger.error(e.getMessage());
		}
	}

	public HashMap<String, String> recogerDatosCola(String mensajeSolicitud) throws IOException {


		TramitacionModuleMDB.logger.error("Inicio recogerTipoMensaje");
		Document datosDocumento = null;

		HashMap<String, String> myHash = new HashMap<String, String>();

		try {
			datosDocumento = this.createDocUTF8(mensajeSolicitud.toString());

		} catch (Exception e) {
			TramitacionModuleMDB.logger.error("xmlColas error UTF8: " + e.getMessage());
		}

		try {

			NodeList nodosPadre = null;
			if (datosDocumento != null) {
				nodosPadre = datosDocumento.getElementsByTagName("NotificationBody");
			}
			if (nodosPadre != null) {
				int numNodosPadre = nodosPadre.item(Constantes.MAGIC_NUMBER_0).getChildNodes().getLength();

				if (numNodosPadre != Constantes.MAGIC_NUMBER_0) {
					for (int i = 0; i < numNodosPadre; i++) { // Vienen X
						NodeList nodos2 = nodosPadre.item(Constantes.MAGIC_NUMBER_0).getChildNodes().item(i)
								.getChildNodes();

						int numElementos = nodosPadre.item(Constantes.MAGIC_NUMBER_0).getChildNodes().item(i)
								.getChildNodes().getLength();

						String valorName = "";
						String valorDato = "";
						for (int f = 0; f < numElementos; f++) { // me vienen 2
																	// elementos
							Node nodoValorName = nodos2.item(f);

							String strValorName = nodos2.item(f).getNodeName();
							String strValorN = "0";

							if ("Name".equals(strValorName)) {
								if (nodoValorName.getFirstChild() != null && !"returnReceipt"
										.equalsIgnoreCase(nodoValorName.getFirstChild().getNodeValue())) {
									valorName = nodoValorName.getFirstChild().getNodeValue();
								} else {
									valorName = "";
									strValorN = "1";
								}

							}
							if ("Value".equals(strValorName)) {

								if (!"1".equalsIgnoreCase(strValorN)) {
									if (nodoValorName.getFirstChild() != null) {
										if (Constantes.VALUE.equalsIgnoreCase(valorName)
												|| Constantes.DELIVERED_INFO.equalsIgnoreCase(valorName)) {
											if (nodoValorName.getTextContent() != null) {
												valorDato = nodoValorName.getTextContent().toString();

											}
										} else {
											valorDato = nodoValorName.getFirstChild().getNodeValue();

										}
									}
								} else {
									valorDato = "";
								}

							}

						}

						if (!"".equalsIgnoreCase(valorName.trim())) {
							try {
								myHash.put(valorName, valorDato.toString().trim());
							} catch (Exception e) {
								TramitacionModuleMDB.logger.error("Error recogerdatos colas " + e.getMessage());
							}
						}

					} // fin for
				}
			}

		} catch (Exception e) {
			TramitacionModuleMDB.logger.error("Error obteniendo los valores de la solicitud:" + e.getMessage());
		}

			String xmlTransformado = mensajeSolicitud.toString();
			TramitacionModuleMDB.logger.error("xmlTransformado " + xmlTransformado);
			xmlTransformado = xmlTransformado.replaceAll("&lt;", "<");
			xmlTransformado = xmlTransformado.replaceAll("&gt;", ">");
			TramitacionModuleMDB.logger.error("xmlTransformado " + xmlTransformado);
			Document documentoTrasformado;
			try {
				documentoTrasformado = TramitacionModuleMDB.stringToDocument(xmlTransformado);
				String codigo = TramitacionModuleMDB.buscarDomString(documentoTrasformado,
						"//xmlValue/RecursoCenso/datosGenerales/codigo/text()");
				TramitacionModuleMDB.logger.error("codigo:" + codigo);

				String signatura = TramitacionModuleMDB.buscarDomString(documentoTrasformado,
						"//xmlValue/RecursoCenso/datosGenerales/signatura/text()");
				TramitacionModuleMDB.logger.error("signatura:" + signatura);

				String urlFichaPortal = TramitacionModuleMDB.buscarDomString(documentoTrasformado,
						"//xmlValue/RecursoCenso/datosGenerales/urlFichaPortal/text()");
				TramitacionModuleMDB.logger.error("urlFichaPortal:" + urlFichaPortal);


				myHash.put("codigo", codigo);
				myHash.put("signatura", signatura);
				myHash.put("urlFichaPortal", urlFichaPortal);

			} catch (Exception e) {
				TramitacionModuleMDB.logger.error("Error transformando el mensaje a document:" + e.getMessage());
			}
		return myHash;

	}
	private Document createDocUTF8(String xml) throws Exception {
		try {
			return (this.buildDocument(xml, "UTF-8"));
		} catch (Exception e) {
			throw new Exception("Error createDocUTF8", e);
		}
	}
	private Document buildDocument(String strPfXML, String strPfEnconding) throws UnsupportedEncodingException, SAXException, IOException, ParserConfigurationException {
		Document doc = null;
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

		DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

		doc = documentBuilder.parse((InputStream) new ByteArrayInputStream(strPfXML.getBytes(strPfEnconding)));

		return (doc);
	}
	private static Document stringToDocument(String textoXML) throws Exception {

		Document document = null;

		try {

			DocumentBuilderFactory factory = null;
			DocumentBuilder builder = null;

			factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(false);
			factory.setIgnoringElementContentWhitespace(true);
			builder = factory.newDocumentBuilder();
			StringReader stringIn = new StringReader(textoXML);
			document = builder.parse(new InputSource(stringIn));

			// crear y aÃ±adir la pi

			ProcessingInstruction pi = document.createProcessingInstruction("xml",
					"version=\"1.0\" encoding=\"ISO-8859-1\"");
			document.appendChild(pi);

		} catch (Exception ex) {
			throw new Exception("Excepcion en stringToDocument:", ex);
		}

		return document;

	}
	/**
	 * Clase necesaria en xpath para xml con namespaces
	 *
	 */
	private static String buscarDomString(Document docDom, String strPath) {

		NodeList NodeLiResultado = null;
		String strValor = "";

		try {

			NodeLiResultado = XPathAPI.selectNodeList(docDom, strPath);

			if (NodeLiResultado.getLength() != 0) {
				strValor = (String) NodeLiResultado.item(0).getNodeValue();
			} else {
				strValor = "";
			}

		} catch (Exception ex) {
			ex.printStackTrace(System.out);
		}

		return strValor;
	}
}
