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.ComunicacionProcedimiento;
import com.ejie.ab04b.model.DatosAviso;
import com.ejie.ab04b.model.DocumentoOS2;
import com.ejie.ab04b.model.OS2;
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 = "ppsOs2Service")
public class PPSOS2Service extends PPSService {

	/**
	 * os2 OS2 listaDocumentos List<DocumentoOS2> ContextSubmission.
	 * 
	 * @param os2
	 *            the os 2
	 * @param listaDocumentos
	 *            the lista documentos
	 * @return the context submission
	 */
	public ContextSubmission crearContextSubmission(OS2 os2,
			List<DocumentoOS2> listaDocumentos) {

		ContextSubmission ctxSubmission = null;

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

		ctxSubmission = this.crearContextSubmission(procedureId);

		// datos de registro
		if (Constantes.VALUE_NO.equals(os2.getDeseaRegistrar060())) {
			ctxSubmission.setMustRegistry(Constantes.VALUE_NO);
			ctxSubmission.setRegistryNumber(os2.getNumReg060());
			ctxSubmission.setRegistryTimestamp(Utilities.getInstance()
					.dateToStringPPS(os2.getFecReg060()));
		}

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

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

		// submissionType y submissionTypeName
		ctxSubmission.setSubmissionType(
				ConstantesPlateaTramitacion.SUBMISSIONTYPE_SOLIC_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(
				os2, LocaleContextHolder.getLocale()));

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

		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) {

		OS2 os2 = (OS2) comunicacion;

		// TODO sacar bien los datos del solicitante
		ctxSubmission.setSenderID(os2.getNumdoc060());
		ctxSubmission.setSenderName(os2.getNomemp060());
		// 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) {

		OS2 os2 = (OS2) comunicacion;

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

		appInfo.setLanguage(locale.getLanguage());

		return appInfo;
	}

	/**
	 * Devuelve la informacion de Notification de la parte ApplicantInfo para
	 * una solicitud
	 * 
	 * os2 OS2
	 * 
	 * Notification.
	 * 
	 * @param os2
	 *            the os 2
	 * @return the notification applicant info
	 */

	private Notification getNotificationApplicantInfo(OS2 os2) {
		Notification notif = new Notification();

		Addressee addressee = new Addressee();

		if (os2 != null) {
			// TODO obtener bien los datos del solicitante
			addressee.setAddresseeID(os2.getNumdoc060());
			addressee.setAddresseeName(os2.getNomemp060());
		}
		notif.setAddressee(addressee);

		Channel channel = PPSUtils.getInstance()
				.construirChannel(os2.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
	 * 
	 * os2 OS2 Persons.
	 * 
	 * @param os2
	 *            the os 2
	 * @return the personas context submission
	 */
	private Persons getPersonasContextSubmission(OS2 os2) {

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

	}

	/**
	 * Devuelve un objeto Person para el ContextSubmission
	 * 
	 * os2 OS2 Person.
	 * 
	 * @param os2
	 *            the os 2
	 * @return the persona
	 */
	private Person getPersona(OS2 os2) {

		Person person = new Person();

		if (null != os2) {
			// TODO obtener los datos reales del solicitante
			person.setId(os2.getNumdoc060());
			person.setName(os2.getNomemp060());

			String tipoPersona = null;
			if (os2 != null) {
				// TODO obtener los datos reales del solicitante
				if (ValidadorNifCifNie.checkCif(os2.getNumdoc060())) {
					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 (os2.getDatosNotificacion().getListaDatosAviso() != null) {
				com.ejie.platea.generic.xml.ObjectFactory of = new com.ejie.platea.generic.xml.ObjectFactory();
				for (DatosAviso datosAviso : os2.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(OS2 os2) {

		Person person = null;

		if (null != os2 && os2.getNumdocrepresentante060() != null
				&& os2.getNomrepresentante060() != null) {

			person = new Person();
			// TODO obtener los datos reales del solicitante
			person.setId(os2.getNumdocrepresentante060());
			person.setName(os2.getNomrepresentante060());

			String tipoPersona = null;
			if (os2 != null) {
				// TODO obtener los datos reales del solicitante
				if (ValidadorNifCifNie
						.checkCif(os2.getNumdocrepresentante060())) {
					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 (os2.getDatosNotificacion().getListaDatosAviso() != null) {
				com.ejie.platea.generic.xml.ObjectFactory of = new com.ejie.platea.generic.xml.ObjectFactory();
				for (DatosAviso datosAviso : os2.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 os2 OS2
	 * 
	 * String con un trozo XML con la estructura deseada
	 * 
	 * @param listaDocumentos
	 *            the lista documentos
	 * @param os2
	 *            the os 2
	 * @return the xml documents context submission
	 */
	public Documents getXmlDocumentsContextSubmission(
			List<DocumentoOS2> listaDocumentos, OS2 os2) {

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

		if (listaDocumentos != null && listaDocumentos.size() > 0) {
			RoleName roleName = null;
			DocumentoOS2 doc = null;
			for (int i = 0; i < listaDocumentos.size(); i++) {
				doc = listaDocumentos.get(i);
				if (doc.getRutaPif094() != 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.getOidDokusi094());
					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.getNombreDoc094());
					document.setExtension(
							new StringBuilder(Constantes.SEPARADOR_PUNTO)
									.append(Utilities.getInstance()
											.obtenerExtensionFichero(
													doc.getNombreDoc094()))
									.toString());
					// document.setOid(doc.getOidDokusi094());
					document.setLocation(doc.getOidDokusi094());
				}

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

		}
		return documents;
	}

	/**
	 * os2 OS2 String.
	 * 
	 * @param os2
	 *            the os 2
	 * @return the string
	 */
	private String obtenerSerieDocumental(OS2 os2) {
		String codTerritorio = ToolkitUtils.getInstance()
				.obtenerTerritorioSolicitudOS2(os2);
		return DokusiUtils.getInstance()
				.obtenerSerieDocumentalOS(codTerritorio);
	}

}
