package com.ejie.m62fb.service.registroVPP;

import java.util.ArrayList;
import java.util.List;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.ejie.m62fb.utils.format.FormatUtils;
import com.ejie.m62fb.model.SolicitudReserva;
import com.ejie.m62fb.model.ViviendaSolicitada;
import com.ejie.m62fb.model.tipos.RegimenAcceso;
import com.ejie.m62fb.model.tipos.RegimenTenencia;
import com.ejie.m62fb.utils.sql.Utilidades;
import com.ejie.m62fb.ws.client.impl.PlateaService;

/**
 * IntegracionServiceImpl.
 * 
XXXX
 */
@Service(value = "integracionService")
public class IntegracionServiceImpl implements IntegracionService {

	// Paths xml R02_REQUEST
	private static final String PATH_REQUEST_FOLDER_ID = "/contextSubmissionEvent/folderID";
	private static final String PATH_REQUEST_SOLICITUD_ID = "/contextSubmissionEvent/solicitudID";
	// Paths xml R02_TASK
	private static final String PATH_TASK_FOLDER_ID = "/task/folderID";
	private static final String PATH_TASK_FOLDER_NUMBER = "/task/folderNumber";

	@Autowired
	private SolicitudReservaService solicitudReservaService;

	@Autowired
	private PlateaService plateaService;

	/**
	 * Crea la solicitud de reserva en M62FB, obteneido los datos de la
	 * solicitud
	 * 
	 * SIN SEGURIDAD, Se llama desde el MDB
	 * 
	 * @param xmlValue
	 *            String (folderId, solicitudId)
	 * @throws Exception
	 *             e
	 */
	@Override
	public void informarSolicitudReserva(String xmlValue) throws Exception {
		// Recuperamos mediante xPath los valores que necesitamos
		Document xmlDocument = Utilidades.parseStringToDocument(xmlValue);
		XPath xPath = XPathFactory.newInstance().newXPath();

		// Recuperar folderId
		String folderId = xPath.compile(PATH_REQUEST_FOLDER_ID).evaluate(
				xmlDocument);
		// Recuperar folderNumber
		String solicitudId = xPath.compile(PATH_REQUEST_SOLICITUD_ID).evaluate(
				xmlDocument);

		// Recuperar informacion de la Solicitud
		String xmlRespuesta = this.plateaService.getRequestInformation(
				solicitudId, folderId);

		// Parsear Respuesta
		SolicitudReserva solicitudReserva = this
				.parsearSolicitudReserva(xmlRespuesta);
		solicitudReserva.setIdExpedientePlatea(folderId);

		// Guardar SolicitudReserva
		this.solicitudReservaService.guardarSolicitudReserva(solicitudReserva);
	}

	/**
	 * Actualiza el estado de una solicitud para que M62FB "sepa" que se ha
	 * realizado la apertura
	 * 
	 * SIN SEGURIDAD, Se llama desde el MDB
	 * 
	 * @param xmlValue
	 *            String (folderId, folderNumber)
	 * @throws Exception
	 *             e
	 */
	@Override
	public void informarApertura(String xmlValue) throws Exception {
		// Recuperamos mediante xPath los valores que necesitamos
		Document xmlDocument = Utilidades.parseStringToDocument(xmlValue);
		XPath xPath = XPathFactory.newInstance().newXPath();

		// Recuperar folderId
		String folderId = xPath.compile(PATH_TASK_FOLDER_ID).evaluate(
				xmlDocument);
		// Recuperar folderNumber
		String folderNumber = xPath.compile(PATH_TASK_FOLDER_NUMBER).evaluate(
				xmlDocument);

		// Informar campos a Actualizar
		SolicitudReserva solicitudReserva = new SolicitudReserva();
		solicitudReserva.setIdExpedientePlatea(folderId);
		solicitudReserva.setNumExpedientePlatea(folderNumber);

		// Actualizar Estado Apertura
		this.solicitudReservaService.updateEstadoApertura(solicitudReserva);
	}

	/**
	 * Actualiza el estado de una solicitud para que M62FB "sepa" que se ha
	 * realizado la Notificacion de resolucion
	 * 
	 * SIN SEGURIDAD, Se llama desde el MDB
	 * 
	 * @param xmlValue
	 *            String (folderId)
	 * @throws Exception
	 *             e
	 */
	@Override
	public void informarNotificacion(String xmlValue) throws Exception {
		// Recuperamos mediante xPath los valores que necesitamos
		Document xmlDocument = Utilidades.parseStringToDocument(xmlValue);
		XPath xPath = XPathFactory.newInstance().newXPath();

		// Recuperar folderId
		String folderId = xPath.compile(PATH_TASK_FOLDER_ID).evaluate(
				xmlDocument);

		// Informar campos a Actualizar
		SolicitudReserva solicitudReserva = new SolicitudReserva();
		solicitudReserva.setIdExpedientePlatea(folderId);

		// Actualizar Estado Notificacion
		this.solicitudReservaService.updateEstadoNotificacion(solicitudReserva);
	}

	/**
	 * Parsea el xml recibido a una SolicitudRespuesta
	 * 
	 * @param xmlRespuesta
	 *            String
	 * @return SolicitudReserva
	 * @throws Exception
	 *             e
	 */
	private SolicitudReserva parsearSolicitudReserva(String xmlRespuesta)
			throws Exception {

		final String PATH_ENTIDAD = "/ejgvDocument/body/detailInfo/datosHolder1/entidad";
		final String PATH_DEPARTAMENTO = "/ejgvDocument/body/detailInfo/datosHolder1/departamento";
		final String PATH_DIRECCION = "/ejgvDocument/body/detailInfo/datosHolder1/direccion";
		final String PATH_TELEFONO = "/ejgvDocument/body/detailInfo/datosHolder1/telefono";
		final String PATH_EMAIL = "/ejgvDocument/body/detailInfo/datosHolder1/direccionElectronica";
		final String PATH_NOMBRE = "/ejgvDocument/body/ApplicantInfo/persons/person/name";
		final String PATH_APE1 = "/ejgvDocument/body/ApplicantInfo/persons/person/ape1";
		final String PATH_APE2 = "/ejgvDocument/body/ApplicantInfo/persons/person/ape2";

		final String PATH_ELEMENTOGR = "/ejgvDocument/body/detailInfo/datosViviendas/grupoViviendas/elementoGR";

		// Recuperamos mediante xPath los valores que necesitamos
		Document xmlDocument = Utilidades.parseStringToDocument(xmlRespuesta);
		XPath xPath = XPathFactory.newInstance().newXPath();

		// Datos Solicitud
		SolicitudReserva solReserva = new SolicitudReserva();
		// DesEntidadSolic
		solReserva.setDesEntidadSolic(xPath.compile(PATH_ENTIDAD).evaluate(
				xmlDocument));
		// DesDptoSolic
		solReserva.setDesDptoSolic(xPath.compile(PATH_DEPARTAMENTO).evaluate(
				xmlDocument));
		// DesDireccion
		solReserva.setDesDireccion(xPath.compile(PATH_DIRECCION).evaluate(
				xmlDocument));
		// NumTelefono
		solReserva.setNumTelefono(xPath.compile(PATH_TELEFONO).evaluate(
				xmlDocument));
		// DirEmail
		solReserva.setDirEmail(xPath.compile(PATH_EMAIL).evaluate(xmlDocument));

		// DesInterlocutor
		StringBuilder nombreCompleto = new StringBuilder();
		String nombre = xPath.compile(PATH_NOMBRE).evaluate(xmlDocument);
		String apellido1 = xPath.compile(PATH_APE1).evaluate(xmlDocument);
		String apellido2 = xPath.compile(PATH_APE2).evaluate(xmlDocument);
		nombreCompleto.append(nombre).append(" ").append(apellido1).append(" ")
				.append(apellido2);
		solReserva.setDesInterlocutor(nombreCompleto.toString());

		// Lista Viviendas Solicitadas
		NodeList nodeList = (NodeList) xPath.compile(PATH_ELEMENTOGR).evaluate(
				xmlDocument, XPathConstants.NODESET);
		List<ViviendaSolicitada> listVivSolicitadas = new ArrayList<ViviendaSolicitada>();
		for (int i = 1; i <= nodeList.getLength(); i++) {
			// Vivienda Solicitada
			listVivSolicitadas.add(this.parsearViviendaSolicitada(xmlDocument,
					i));
		}
		solReserva.setListViviendasSolicitadas(listVivSolicitadas);

		return solReserva;
	}

	/**
	 * Parsea una Vivienda Solicitada, la de la posicion dada
	 * 
	 * @param xmlDocument
	 *            Document
	 * @param index
	 *            int
	 * @return ViviendaSolicitada
	 * @throws Exception
	 *             e
	 */
	private ViviendaSolicitada parsearViviendaSolicitada(Document xmlDocument,
			int index) throws Exception {

		final String PATH_ELEMENTO = "/ejgvDocument/body/detailInfo/datosViviendas/grupoViviendas/elementoGR[";
		final String PATH_VALORES = "/ejgvDocument/body/detailInfo/datosViviendas/grupoViviendas/elementoGRValores[";
		// Paths desde elementoGR
		final String PATH_MOTIVO = "]/motivoReserva";
		final String PATH_ADAPTADA = "]/adaptada";
		final String PATH_HABIT = "]/habitaciones";
		final String PATH_METROS = "]/metros";
		final String PATH_RECEPTOR = "]/receptor";
		final String PATH_OBSERV = "]/observaciones";
		// Paths desde elementoGRValores
		final String PATH_PROVINCIA = "]/provincia";
		final String PATH_MUNICIPIO = "]/municipio";
		final String PATH_ACCESO = "]/regimenacceso";
		final String PATH_TENENCIA = "]/regimentenencia";

		// Recuperamos mediante xPath los valores que necesitamos
		XPath xPath = XPathFactory.newInstance().newXPath();

		// Datos Vivienda Solicitada
		ViviendaSolicitada vivSolicitada = new ViviendaSolicitada();
		// NumOrden
		vivSolicitada.setNumOrden(Long.valueOf(index));
		// DesMotivoReserva
		vivSolicitada.setDesMotivoReserva(xPath.compile(
				PATH_ELEMENTO + index + PATH_MOTIVO).evaluate(xmlDocument));
		// CodProvincia
		vivSolicitada.setCodProvincia(xPath.compile(
				PATH_VALORES + index + PATH_PROVINCIA).evaluate(xmlDocument));
		// CodMunicipio
		vivSolicitada.setCodMunicipio(xPath.compile(
				PATH_VALORES + index + PATH_MUNICIPIO).evaluate(xmlDocument));
		// RegimenAcceso
		vivSolicitada.setRegimenAcceso(new RegimenAcceso(xPath.compile(
				PATH_VALORES + index + PATH_ACCESO).evaluate(xmlDocument)));
		// RegimenTenencia
		vivSolicitada.setRegimenTenencia(new RegimenTenencia(xPath.compile(
				PATH_VALORES + index + PATH_TENENCIA).evaluate(xmlDocument)));
		// IndVivAdaptada (["S"], [])
		String adaptada = xPath.compile(PATH_ELEMENTO + index + PATH_ADAPTADA)
				.evaluate(xmlDocument);
		vivSolicitada.setIndVivAdaptada(adaptada.replace("[", "")
				.replace("]", "").replace("\"", ""));
		// NumDormitorios
		vivSolicitada.setNumDormitorios(Long.valueOf(xPath.compile(
				PATH_ELEMENTO + index + PATH_HABIT).evaluate(xmlDocument)));
		// SupUtilViv
		vivSolicitada.setSupUtilViv(FormatUtils.convertirADecimal(xPath
				.compile(PATH_ELEMENTO + index + PATH_METROS).evaluate(
						xmlDocument)));
		// DesReceptor
		vivSolicitada.setDesReceptor(xPath.compile(
				PATH_ELEMENTO + index + PATH_RECEPTOR).evaluate(xmlDocument));
		// TexObservaciones
		vivSolicitada.setTexObservaciones(xPath.compile(
				PATH_ELEMENTO + index + PATH_OBSERV).evaluate(xmlDocument));

		return vivSolicitada;
	}
}
