package com.ejie.ab04b.service.platea;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ejie.ab04b.constantes.Constantes;
import com.ejie.ab04b.constantes.ConstantesPlateaTramitacion;
import com.ejie.ab04b.model.DatosAviso;
import com.ejie.ab04b.model.DatosLocalizacion;
import com.ejie.ab04b.model.DatosNotificacion;
import com.ejie.ab04b.util.PlateaTramitacionUtils;
import com.ejie.ab04b.util.Utilities;
import com.ejie.ab04b.util.seguridad.UtilSeguridad;
import com.ejie.ab04b.webservice.client.expediente.Q99RReeFolderFacadeWSSoap;
import com.ejie.ab04b.webservice.client.q99mpps.Q99MPPSFacadeWSSoap;
import com.ejie.ab04b.webservice.client.ree.ArrayOfString;
import com.ejie.ab04b.webservice.client.ree.Q99YTramitacionFacadeWSSoap;
import com.ejie.app.xml.Addressee;
import com.ejie.app.xml.Applicant;
import com.ejie.app.xml.Notice;
import com.ejie.app.xml.NoticeChannel;
import com.ejie.app.xml.Notification;
import com.ejie.app.xml.NotificationChannel;
import com.ejie.app.xml.Person;
import com.ejie.app.xml.Persons;
import com.ejie.ct.xml.Expedient;
import com.ejie.ct.xml.FolderDocumentList;
import com.ejie.ct.xml.InfExpte;
import com.ejie.ct.xml.InfExpteList;
import com.ejie.ct.xml.Participant;

/**
 * @author GFI-NORTE
 *
 */
@Service()
public class ReeService {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(ReeService.class);

	@Autowired()
	private Q99YTramitacionFacadeWSSoap q99YTramitacionFacadeWSSoap;
	@Autowired()
	private Q99RReeFolderFacadeWSSoap q99RReeFolderFacadeWSSoap;
	@Autowired()
	private Q99MPPSFacadeWSSoap q99MPPSFacadeWSSoap;

	/**
	 * Obtiene toda la información de un expediente del REE
	 * 
	 * folderId String InfExpte.
	 *
	 * @param folderId
	 *            the folder id
	 * @return the inf expte
	 */
	public InfExpte obtenerInformacionExpediente(String folderId) {

		String sSessionToken = UtilSeguridad.getInstance().getTokenXLNets();
		String sAuditUser = UtilSeguridad.getInstance().getAuditUser();

		ArrayOfString saFolderIDs = new ArrayOfString();
		saFolderIDs.getString().add(folderId);

		ArrayOfString saParams = new ArrayOfString();
		saParams.getString().add(ConstantesPlateaTramitacion.FOLDERINFO_TODO);

		try {
			String response = this.q99YTramitacionFacadeWSSoap.getFolderInfo(
					sSessionToken, saFolderIDs, saParams, sAuditUser);

			InfExpteList listaExpedientes = PlateaTramitacionUtils.getInstance()
					.getPlateaResponseAsInfExpList(response);
			InfExpte expediente = null;
			if (listaExpedientes != null
					&& listaExpedientes.getInfExpte() != null
					&& !listaExpedientes.getInfExpte().isEmpty()) {
				expediente = listaExpedientes.getInfExpte().get(0);
			}
			return expediente;
		} catch (Exception e) {
			ReeService.LOGGER.info(
					"Entra en la llamada q99RReeFolderFacadeWSSoap.getFolderProceedings",
					e);

			return null;
		}
	}

	/**
	 * Construye un objeto DatosNotificacion a partir de la información obtenida
	 * del método getFolderInfo del REE. Si el expediente no es migrado,
	 * devuelve los códigos Nora de provincia, municipio y localidad. En caso
	 * contrario, devuelve las descripciones sin código.
	 * 
	 * folderId String esMigrado boolean indica si el folderId hace referencia a
	 * un expediente migrado DatosNotificacion En expedientes muy antiguos, si
	 * no tienen Participant, se devuelve null
	 *
	 * @param folderId
	 *            the folder id
	 * @param esMigrado
	 *            the es migrado
	 * @return the datos notificacion
	 */
	public DatosNotificacion obtenerDatosNotificacionExpedienteREE(
			String folderId, boolean esMigrado) {

		InfExpte expediente = this.obtenerInformacionExpediente(folderId);

		DatosNotificacion datosNotificacion = null;
		if (expediente != null && expediente.getParticipantList() != null
				&& expediente.getParticipantList().getParticipant() != null
				&& !expediente.getParticipantList().getParticipant()
						.isEmpty()) {
			Participant participant = expediente.getParticipantList()
					.getParticipant()
					.get(expediente.getParticipantList().getParticipant().size()
							- 1);

			datosNotificacion = PlateaTramitacionUtils.getInstance()
					.construirDatosNotificacionFromParticipant(participant,
							esMigrado);
		}

		return datosNotificacion;
	}

	/**
	 * Modificar en el REE los datos de notificación y de aviso de un expediente
	 * 
	 * folderId String datosNotificacion DatosNotificacion.
	 *
	 * @param folderId
	 *            the folder id
	 * @param datosNotificacion
	 *            the datos notificacion
	 */
	public void modificarDatosNotificacionExpedienteREE(String folderId,
			DatosNotificacion datosNotificacion) {

		String sSessionToken = UtilSeguridad.getInstance().getTokenXLNets();

		// Primero obtenemos los datos del expediente para mantener los datos
		// del solicitante
		InfExpte expediente = this.obtenerInformacionExpediente(folderId);

		Applicant applicant = new Applicant();
		Addressee addressee = new Addressee();

		// Rellenamos la información básica de la participación, ya que la
		// mantenemos con los mismos datos
		this.rellenarInfoBasicaApplicantExpediente(applicant, expediente,
				addressee);
		if (Constantes.IDIOMA_NOTIF_EUSKERA
				.equals(datosNotificacion.getIdioma066())) {
			applicant.setLanguage(Constantes.EU);
		} else {
			applicant.setLanguage(Constantes.ES);
		}

		// Rellenamos con los nuevos datos de notificación
		applicant.getNotification().setAddressee(addressee);
		NotificationChannel notificationChannel = new NotificationChannel();
		notificationChannel.setType(
				PlateaTramitacionUtils.getInstance().obtenerNotificationFormat(
						datosNotificacion.getCanalnotif066()));
		if (Constantes.CANAL_NOTIF_POSTAL
				.equals(datosNotificacion.getCanalnotif066())) {
			// Canal notificación postal
			com.ejie.ainit.xml.PostalAddress postalAddress = new com.ejie.ainit.xml.PostalAddress();
			DatosLocalizacion datosLocalizacion = datosNotificacion
					.getDatosLocalizacion();
			postalAddress.setProvincia(PlateaTramitacionUtils.getInstance()
					.construirAinitDescriptionType(
							PlateaTramitacionUtils.getInstance()
									.construirValorNoraContextSubmissionChannelInfo(
											datosLocalizacion.getProvincia()
													.getCodProvincia(),
											datosLocalizacion.getProvincia()
													.getDescripcion()),
							PlateaTramitacionUtils.getInstance()
									.construirValorNoraContextSubmissionChannelInfo(
											datosLocalizacion.getProvincia()
													.getCodProvincia(),
											datosLocalizacion.getProvincia()
													.getDescripcion())));
			postalAddress.setMunicipio(PlateaTramitacionUtils.getInstance()
					.construirValorNoraContextSubmissionChannelInfo(
							datosLocalizacion.getMunicipio().getCodMunicipio(),
							datosLocalizacion.getMunicipio().getDescripcion()));
			postalAddress.setLocalidad(PlateaTramitacionUtils.getInstance()
					.construirValorNoraContextSubmissionChannelInfo(
							datosLocalizacion.getLocalidad().getCodLocalidad(),
							datosLocalizacion.getLocalidad().getDescripcion()));
			postalAddress.setDireccion(datosLocalizacion.getCalle067());
			postalAddress.setPortal(datosLocalizacion.getPortal067());
			postalAddress.setPiso(datosLocalizacion.getPiso067());
			postalAddress.setLetra(datosLocalizacion.getPuerta067());
			postalAddress.setCp(datosLocalizacion.getCodpostal067());
			notificationChannel.setPostalAddress(postalAddress);
		} else {
			notificationChannel.setElectronicAddress("");
		}
		applicant.getNotification().setChannel(notificationChannel);

		// Rellenamos con los nuevos datos de aviso
		if (datosNotificacion.getListaDatosAviso() != null
				&& !datosNotificacion.getListaDatosAviso().isEmpty()) {
			for (DatosAviso datosAviso : datosNotificacion
					.getListaDatosAviso()) {
				Notice notice = new Notice();

				notice.setAddressee(addressee);
				NoticeChannel noticeChannel = new NoticeChannel();
				noticeChannel.setType(PlateaTramitacionUtils.getInstance()
						.obtenerNotificationChannelType(
								datosAviso.getTipo068()));
				if (Constantes.CANAL_AVISO_EMAIL
						.equals(datosAviso.getTipo068())) {
					noticeChannel.setEmailAddress(datosAviso.getValor068());
				} else if (Constantes.CANAL_AVISO_SMS
						.equals(datosAviso.getTipo068())) {
					noticeChannel.setSmsNumber(datosAviso.getValor068());
				}
				notice.setChannel(noticeChannel);

				applicant.getNotices().getNotice().add(notice);
			}
		}

		String sApplicantInfo = PlateaTramitacionUtils.getInstance()
				.unparseApplicantToString(applicant);

		// Eliminamos las referencias al namespace ns2 por el objeto
		// postalAddress (ainit)
		sApplicantInfo = sApplicantInfo
				.replaceAll("xmlns:ns2=\"com/ejie/ainit/xml\"", "");
		sApplicantInfo = sApplicantInfo.replaceAll("ns2:", "");

		this.q99RReeFolderFacadeWSSoap.updateApplicantFolderParticipant(
				sSessionToken, folderId, sApplicantInfo);
	}

	/**
	 * applicant Applicant expediente expediente addressee Addressee.
	 *
	 * @param applicant
	 *            the applicant
	 * @param expediente
	 *            the expediente
	 * @param addressee
	 *            the addressee
	 */
	private void rellenarInfoBasicaApplicantExpediente(Applicant applicant,
			InfExpte expediente, Addressee addressee) {

		com.ejie.app.xml.Person person = new Person();

		if (expediente.getParticipantList() != null
				&& expediente.getParticipantList().getParticipant() != null
				&& !expediente.getParticipantList().getParticipant()
						.isEmpty()) {

			// Obtenemos el objeto participant del expediente
			Participant participant = expediente.getParticipantList()
					.getParticipant().get(0);

			// participantID
			applicant.setParticipantID(participant.getParticipantID());
			if (participant.getRoleList() != null
					&& participant.getRoleList().getRole() != null
					&& !participant.getRoleList().getRole().isEmpty()) {
				// role
				applicant.setRole(participant.getRoleList().getRole().get(0)
						.getRoleName());
			}
			// language
			applicant.setLanguage(participant.getLanguage());

			if (participant.getPersonList() != null
					&& participant.getPersonList().getPerson() != null
					&& !participant.getPersonList().getPerson().isEmpty()) {

				// Obtenemos el objeto person del expediente
				com.ejie.ct.xml.Person personExp = participant.getPersonList()
						.getPerson().get(0);

				// person
				person.setID(personExp.getID());
				person.setName(personExp.getName());
				person.setApellido1(personExp.getApe1());
				person.setApellido2(personExp.getApe2());
				person.setID(personExp.getID());
				person.setHoldership(personExp.getHoldership());
				person.setPersonType(personExp.getPersonType());
				person.setPersonID(personExp.getPersonID());
			}
		}

		applicant.setPersons(new Persons());
		applicant.getPersons().getPerson().add(person);

		// inicializamos notification
		Notification notification = new Notification();
		applicant.setNotification(notification);

		// inicializamos notices
		applicant.setNotices(new com.ejie.app.xml.Applicant.Notices());

		// rellenamos addressee
		addressee.setID(person.getID());
		addressee.setName(Utilities.getInstance().conformarNombreCompleto(
				person.getName(), person.getApellido1(),
				person.getApellido2()));
	}

	/**
	 * folderId String Expedient.
	 *
	 * @param folderId
	 *            the folder id
	 * @return the expedient
	 */
	public Expedient obtenerHistorialExpediente(String folderId) {

		ReeService.LOGGER.info(
				"Entra en obtenerHistorialExpediente: folderId {}", folderId);

		String sSessionToken = UtilSeguridad.getInstance().getTokenXLNets();

		try {
			String response = this.q99RReeFolderFacadeWSSoap
					.getFolderProceedings(sSessionToken, folderId);

			return PlateaTramitacionUtils.getInstance()
					.getPlateaResponseAsExpedient(response);
		} catch (Exception e) {
			ReeService.LOGGER.info(
					"Entra en la llamada q99RReeFolderFacadeWSSoap.getFolderProceedings",
					e);

			return null;
		}
	}

	/**
	 * contextSubmission String String.
	 *
	 * @param contextSubmission
	 *            the context submission
	 * @return the string
	 */
	public String enviarSolicitud(String contextSubmission) {

		ReeService.LOGGER.info("Entra en enviarSolicitud: contextSubmission {}",
				contextSubmission);

		String sSessionToken = UtilSeguridad.getInstance().getTokenXLNets();

		try {
			return this.q99MPPSFacadeWSSoap.sendEjgvDocumentPresencial(
					sSessionToken, contextSubmission);
		} catch (Exception e) {
			ReeService.LOGGER.info(
					"Entra en la llamada q99MPPSFacadeWSSoap.sendEjgvDocumentPresencial",
					e);

			return null;
		}
	}

	/**
	 * folderId String String.
	 *
	 * @param folderId
	 *            the folder id
	 * @return the folder document list
	 */
	public FolderDocumentList obtenerDocumentosMigrados(String folderId) {

		ReeService.LOGGER.info(
				"Entra en obtenerDocumentosMigrados: folderId {}", folderId);

		String sSessionToken = UtilSeguridad.getInstance().getTokenXLNets();
		String sAuditUser = UtilSeguridad.getInstance().getAuditUser();

		FolderDocumentList fdl = null;

		try {
			String response = this.q99YTramitacionFacadeWSSoap
					.getFolderDocumentsInfoAttributes(sSessionToken, folderId,
							null, sAuditUser);

			fdl = PlateaTramitacionUtils.getInstance()
					.getPlateaResponseAsFolderDocumentList(response);

		} catch (Exception e) {
			ReeService.LOGGER.info(
					"Entra en la llamada q99MPPSFacadeWSSoap.obtenerDocumentosMigrados",
					e);

			return null;
		}

		return fdl;

	}

}
