package com.ejie.ab04b.service.platea;

import java.util.List;
import java.util.Locale;

import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;

import com.ejie.ab04b.constantes.Constantes;
import com.ejie.ab04b.constantes.ConstantesPlateaTramitacion;
import com.ejie.ab04b.model.Buzon;
import com.ejie.ab04b.model.ComunicacionApertura;
import com.ejie.ab04b.model.ComunicacionProcedimiento;
import com.ejie.ab04b.model.DatosAviso;
import com.ejie.ab04b.model.DocumentoAperturas;
import com.ejie.ab04b.util.DokusiUtils;
import com.ejie.ab04b.util.PPSUtils;
import com.ejie.ab04b.util.ToolkitUtils;
import com.ejie.ab04b.util.Utilities;
import com.ejie.ab04b.util.ValidadorNifCifNie;
import com.ejie.ab04b.util.seguridad.UtilSeguridad;
import com.ejie.ctfm.xml.Addressee;
import com.ejie.ctfm.xml.ApplicantInfo;
import com.ejie.ctfm.xml.Channel;
import com.ejie.ctfm.xml.Contact;
import com.ejie.ctfm.xml.Contacts;
import com.ejie.ctfm.xml.ContextSubmission;
import com.ejie.ctfm.xml.Document;
import com.ejie.ctfm.xml.Documents;
import com.ejie.ctfm.xml.Notification;
import com.ejie.ctfm.xml.Person;
import com.ejie.ctfm.xml.Persons;
import com.ejie.platea.generic.xml.RoleName;
import com.ejie.platea.generic.xml.Value;

/**
 * @author GFI-NORTE
 * 
 */
@Service(value = "ppsAportacionService")
public class PPSAportacionService extends PPSService {

	/**
	 * esSubsanacion boolean apertura ComunicacionApertura listaDocumentos List
	 * <DocumentoAperturas> ContextSubmission.
	 * 
	 * @param esSubsanacion
	 *            the es subsanacion
	 * @param apertura
	 *            the apertura
	 * @param listaDocumentos
	 *            the lista documentos
	 * @return the context submission
	 */
	public ContextSubmission crearContextSubmission(boolean esSubsanacion,
			ComunicacionApertura apertura,
			List<DocumentoAperturas> listaDocumentos) {

		ContextSubmission ctxSubmission = null;

		String procedureId = Utilities.getInstance()
				.obtenerProcedureIdApertura();

		ctxSubmission = this.crearContextSubmission(procedureId);

		// Buzón
		Buzon buzon = this.getBuzonService().obtenerBuzon(procedureId,
				apertura.getTerape056());
		ctxSubmission.setMailbox(buzon.getMailbox076());
		ctxSubmission.setProcedureInboxID(buzon.getMailbox076());
		ctxSubmission.setProcedureInboxName(buzon.getMailbox076());

		// datos de registro
		if (Constantes.VALUE_NO.equals(apertura.getDeseaRegistrar())) {
			ctxSubmission.setMustRegistry(Constantes.VALUE_NO);
			ctxSubmission.setRegistryNumber(apertura.getNumReg());
			ctxSubmission.setRegistryTimestamp(Utilities.getInstance()
					.dateToStringPPS(apertura.getFecReg()));
		}

		// sender y registrySender
		this.addContextSubmissionFromSolicitante(ctxSubmission, apertura);

		if (esSubsanacion) {
			// submissionType y submissionTypeName
			ctxSubmission.setSubmissionType(
					ConstantesPlateaTramitacion.SUBMISSIONTYPE_APORT_SUBSANA);
		} else {
			// submissionType y submissionTypeName
			ctxSubmission.setSubmissionType(
					ConstantesPlateaTramitacion.SUBMISSIONTYPE_APORT_PRESEN);
		}
		ctxSubmission.setSubmissionTypeName(
				PPSUtils.getInstance().construirPlateaDescription(
						this.getAppMessageSource().getMessage(
								ConstantesPlateaTramitacion.SUBMISSIONTYPE_DESC_PREFIX
										.concat(ctxSubmission
												.getSubmissionType()),
								null, Constantes.LOCALE_ES),
						this.getAppMessageSource().getMessage(
								ConstantesPlateaTramitacion.SUBMISSIONTYPE_DESC_PREFIX
										.concat(ctxSubmission
												.getSubmissionType()),
								null, Constantes.LOCALE_EU)));

		// applicantInfo
		ctxSubmission.setApplicantInfo(this.getApplicantInfoContextSubmission(
				apertura, LocaleContextHolder.getLocale()));

		// documentos
		ctxSubmission
				.setDaDocumentalSeries(this.obtenerSerieDocumental(apertura));
		ctxSubmission.setDocuments(this
				.getXmlDocumentsContextSubmission(listaDocumentos, apertura));

		ctxSubmission.setFolderID(apertura.getFolderId056());

		return ctxSubmission;

	}

	/**
	 * Agrega al objeto ContextSubmission la informacion de registrySenderid,
	 * registrySenderName, senderId y senderName. Esta informacion depende del
	 * solicitante
	 * 
	 * ctxSubmission ContextSubmission comunicacion ComunicacionProcedimiento
	 * 
	 * @param ctxSubmission
	 *            the ctx submission
	 * @param comunicacion
	 *            the comunicacion
	 */
	@Override()
	protected void addContextSubmissionFromSolicitante(
			ContextSubmission ctxSubmission,
			ComunicacionProcedimiento comunicacion) {

		ComunicacionApertura apertura = (ComunicacionApertura) comunicacion;

		// TODO sacar bien los datos del solicitante
		ctxSubmission.setSenderID(apertura.getNumdoc056());
		ctxSubmission.setSenderName(apertura.getNomemp056());
		// ctxSubmission.setSenderType("1"); // 1-TITULAR 2-REPRESENTANTE
		ctxSubmission.setRegistrySenderID(
				UtilSeguridad.getInstance().getUserCredentials().getPosition());
		ctxSubmission
				.setRegistrySenderName(UtilSeguridad.getInstance().getNombre());
	}

	/**
	 * Crea el apartado applicantInfo del contextSubmission de una solicitud
	 * 
	 * comunicacion ComunicacionProcedimiento locale Locale con el idioma
	 * seleccionado en la aplicacion ApplicantInfo.
	 * 
	 * @param comunicacion
	 *            the comunicacion
	 * @param locale
	 *            the locale
	 * @return the applicant info context submission
	 */
	@Override()
	protected ApplicantInfo getApplicantInfoContextSubmission(
			ComunicacionProcedimiento comunicacion, Locale locale) {

		ComunicacionApertura apertura = (ComunicacionApertura) comunicacion;

		ApplicantInfo appInfo = new ApplicantInfo();
		appInfo.setNotification(this.getNotificationApplicantInfo(apertura));
		appInfo.setPersons(this.getPersonasContextSubmission(apertura));
		// TODO obtener los datos reales del solicitante
		appInfo.setNotices(PPSUtils.getInstance().getNoticesApplicantInfo(
				apertura.getNumdoc056(), apertura.getNomemp056(),
				apertura.getDatosNotificacion().getListaDatosAviso()));

		appInfo.setLanguage(locale.getLanguage());

		return appInfo;
	}

	/**
	 * Devuelve la informacion de Notification de la parte ApplicantInfo para
	 * una solicitud
	 * 
	 * apertura ComunicacionApertura
	 * 
	 * Notification.
	 * 
	 * @param apertura
	 *            the apertura
	 * @return the notification applicant info
	 */

	private Notification getNotificationApplicantInfo(
			ComunicacionApertura apertura) {
		Notification notif = new Notification();

		Addressee addressee = new Addressee();

		addressee.setAddresseeID(apertura.getNumdoc056());
		addressee.setAddresseeName(apertura.getNomemp056());

		notif.setAddressee(addressee);

		Channel channel = PPSUtils.getInstance()
				.construirChannel(apertura.getDatosNotificacion());
		if (channel.getChannelType() != null) {
			notif.setChannel(channel);
		} else {
			// Si no hay datos de notificación porque es una aportación,
			// ponemos
			// todo el objeto Notification a null
			notif = null;
		}

		return notif;
	}

	/**
	 * Devuelve un objeto Persons que representa la informacion de la/s
	 * persona/s de la solicitud
	 * 
	 * apertura ComunicacionApertura Persons.
	 * 
	 * @param apertura
	 *            the apertura
	 * @return the personas context submission
	 */
	private Persons getPersonasContextSubmission(
			ComunicacionApertura apertura) {

		Persons persons = new Persons();
		persons.getPerson().add(this.getPersona(apertura));
		Person repre = this.getPersonaRepresentante(apertura);
		if (repre != null) {
			persons.getPerson().add(repre);
		}

		return persons;

	}

	/**
	 * Devuelve un objeto Person para el ContextSubmission
	 * 
	 * apertura ComunicacionApertura Person.
	 * 
	 * @param apertura
	 *            the apertura
	 * @return the persona
	 */
	private Person getPersona(ComunicacionApertura apertura) {

		Person person = new Person();

		if (null != apertura) {
			// TODO obtener los datos reales del solicitante
			person.setId(apertura.getNumdoc056());
			person.setName(apertura.getNomemp056());

			String tipoPersona = null;
			if (apertura != null) {
				// TODO obtener los datos reales del solicitante
				if (ValidadorNifCifNie.checkCif(apertura.getNumdoc056())) {
					tipoPersona = ConstantesPlateaTramitacion.CS_PERSONTYPE_JURIDICA;
				} else {
					tipoPersona = ConstantesPlateaTramitacion.CS_PERSONTYPE_FISICA;
				}
			}
			person.setPersonType(tipoPersona);

			person.setHolderShip(
					ConstantesPlateaTramitacion.CS_HOLDERSHIP_HOLDER);

			// se refiere a telefono o fax de una persona
			Contacts contacts = new Contacts();
			if (apertura.getDatosNotificacion().getListaDatosAviso() != null) {
				com.ejie.platea.generic.xml.ObjectFactory of = new com.ejie.platea.generic.xml.ObjectFactory();
				for (DatosAviso datosAviso : apertura.getDatosNotificacion()
						.getListaDatosAviso()) {
					Contact contact = new Contact();
					if (Constantes.CANAL_AVISO_SMS
							.equals(datosAviso.getTipo068())) {
						contact.setType(
								ConstantesPlateaTramitacion.CS_CONTACTTYPE_PHONE);
						Value value = new Value();
						value.getContent().add(
								of.createPhoneNumber(datosAviso.getValor068()));
						contact.setValue(value);
						contacts.getContact().add(contact);
					}
				}
			}
			person.setContacts(contacts);
		}

		return person;
	}

	/**
	 * Devuelve un objeto Person para el ContextSubmission
	 * 
	 * apertura ComunicacionApertura Person.
	 * 
	 * @param apertura
	 *            the apertura
	 * @return the persona
	 */
	private Person getPersonaRepresentante(ComunicacionApertura apertura) {

		Person person = null;

		if (null != apertura && apertura.getNumdocrepresentante056() != null
				&& apertura.getNombrerepresentante056() != null) {

			person = new Person();
			// TODO obtener los datos reales del solicitante
			person.setId(apertura.getNumdocrepresentante056());
			person.setName(apertura.getNombrerepresentante056());

			String tipoPersona = null;
			if (apertura != null) {
				// TODO obtener los datos reales del solicitante
				if (ValidadorNifCifNie
						.checkCif(apertura.getNumdocrepresentante056())) {
					tipoPersona = ConstantesPlateaTramitacion.CS_PERSONTYPE_JURIDICA;
				} else {
					tipoPersona = ConstantesPlateaTramitacion.CS_PERSONTYPE_FISICA;
				}
			}
			person.setPersonType(tipoPersona);

			person.setHolderShip(
					ConstantesPlateaTramitacion.CS_HOLDERSHIP_REPRESENTATIVE);

			// se refiere a telefono o fax de una persona
			Contacts contacts = new Contacts();
			if (apertura.getDatosNotificacion().getListaDatosAviso() != null) {
				com.ejie.platea.generic.xml.ObjectFactory of = new com.ejie.platea.generic.xml.ObjectFactory();
				for (DatosAviso datosAviso : apertura.getDatosNotificacion()
						.getListaDatosAviso()) {
					Contact contact = new Contact();
					if (Constantes.CANAL_AVISO_SMS
							.equals(datosAviso.getTipo068())) {
						contact.setType(
								ConstantesPlateaTramitacion.CS_CONTACTTYPE_PHONE);
						Value value = new Value();
						value.getContent().add(
								of.createPhoneNumber(datosAviso.getValor068()));
						contact.setValue(value);
						contacts.getContact().add(contact);
					}
				}
			}
			person.setContacts(contacts);
		}

		return person;
	}

	/**
	 * Devuelve la parte documents que representa la informacion de una lista de
	 * documentos en el ConxtextSubmission. Uno de esos documentos siempre sera
	 * el propio ejgvDocument, del que viene la firma pasada como parametro.
	 * signerId y signerName son los datos del firmante del ejgvDocument, que
	 * son necesarios para la firma
	 * 
	 * listaDocumentos Lista de elementos SolicDocumentos apertura
	 * ComunicacionApertura
	 * 
	 * String con un trozo XML con la estructura deseada
	 * 
	 * @param listaDocumentos
	 *            the lista documentos
	 * @param apertura
	 *            the apertura
	 * @return the xml documents context submission
	 */
	public Documents getXmlDocumentsContextSubmission(
			List<DocumentoAperturas> listaDocumentos,
			ComunicacionApertura apertura) {

		Documents documents = new Documents();
		Document document = null;

		if (listaDocumentos != null && listaDocumentos.size() > 0) {
			RoleName roleName = null;
			DocumentoAperturas doc = null;
			for (int i = 0; i < listaDocumentos.size(); i++) {
				doc = listaDocumentos.get(i);
				if (doc.getRutaPif065() != null) {
					document = new Document(); // NOPMD hay que crear el objeto
					document.setDocumentType(
							ConstantesPlateaTramitacion.DOCUMENT_TYPE_YAEXISTE_DOKUSI);
					document.setFormat(
							ConstantesPlateaTramitacion.DOCUMENT_FORMAT_ELECTRONICO);
					document.setOid(doc.getOidDokusi065());
					document.setRoleId(
							doc.getTipoDocumento().getTipoDocumentalCompleto());
					roleName = new RoleName(); // NOPMD hay que crear
												// el objeto
					roleName.setDescription(
							PPSUtils.getInstance().construirPlateaDescription(
									doc.getTipoDocumento()
											.getDescripcionEs091(),
									doc.getTipoDocumento()
											.getDescripcionEu091()));
					document.setRoleName(roleName);
					document.setSourceName(doc.getNombreDoc065());
					document.setExtension(
							new StringBuilder(Constantes.SEPARADOR_PUNTO)
									.append(Utilities.getInstance()
											.obtenerExtensionFichero(
													doc.getNombreDoc065()))
									.toString());
					// document.setOid(doc.getOidDokusi065());
					document.setLocation(doc.getOidDokusi065());
				}

				documents.getDocument().add(document);
			}

		}
		return documents;
	}

	/**
	 * apertura ComunicacionApertura String.
	 * 
	 * @param apertura
	 *            the apertura
	 * @return the string
	 */
	private String obtenerSerieDocumental(ComunicacionApertura apertura) {
		String codTerritorio = ToolkitUtils.getInstance()
				.obtenerTerritorioSolicitudApertura(apertura);
		return DokusiUtils.getInstance()
				.obtenerSerieDocumentalAperturas(codTerritorio);
	}

}
