package com.ejie.ab04b.evento;

import java.util.Date;
import java.util.concurrent.TimeUnit;

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.constantes.EstadosTareas;
import com.ejie.ab04b.constantes.TipoTareaFlujo;
import com.ejie.ab04b.constantes.TipoTareaPlatea;
import com.ejie.ab04b.constantes.TipoTramiteFlujo;
import com.ejie.ab04b.exception.AB04BException;
import com.ejie.ab04b.exception.AB04BParseException;
import com.ejie.ab04b.model.ComunicacionProcedimiento;
import com.ejie.ab04b.model.DocumentoOS2;
import com.ejie.ab04b.model.OS2;
import com.ejie.ab04b.model.Tarea;
import com.ejie.ab04b.model.TareaOS2;
import com.ejie.ab04b.model.TareaProcedimiento;
import com.ejie.ab04b.model.Tramite;
import com.ejie.ab04b.model.TramiteOS2;
import com.ejie.ab04b.model.TramiteProcedimiento;
import com.ejie.ab04b.service.DocumentoOS2Service;
import com.ejie.ab04b.service.OS2Service;
import com.ejie.ab04b.service.TareaOS2Service;
import com.ejie.ab04b.service.TareaService;
import com.ejie.ab04b.service.TramiteOS2Service;
import com.ejie.ab04b.service.TramiteService;
import com.ejie.ab04b.service.tramitacion.TramitacionOS2Service;
import com.ejie.ab04b.util.PlateaTramitacionUtils;
import com.ejie.ab04b.util.Utilities;
import com.ejie.foldermanagement.xml.ContextSubmissionEvent;
import com.ejie.foldermanagement.xml.DocumentsEvent;
import com.ejie.mbt.xml.Task;

/**
 * @author GFI-NORTE
 *
 */
/**
 * @author GFI-NORTE
 * 
 */
@Service(value = "manejadorTareasOS2")
public class ManejadorTareasOS2 implements ManejadorTareas {

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

	@Autowired()
	private OS2Service os2Service;
	@Autowired()
	private TramiteOS2Service tramiteOS2sService;
	@Autowired()
	private TareaOS2Service tareaOS2Service;
	@Autowired()
	private DocumentoOS2Service documentoOS2Service;
	@Autowired()
	private TramiteService tramiteService;

	@Autowired()
	private TramitacionOS2Service tramitacionOS2Service;

	@Autowired()
	private TareaService tareaService;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#getDocCorrExpedienteByFolderId(
	 * java.lang.String)
	 */
	@Override()
	public String getDocCorrExpedienteByFolderId(String folderId) {

		return this.os2Service.findByFolderId(folderId).getDoccorrecta060();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#obtenerFolderNumberByFolderId(java
	 * .lang.String)
	 */
	@Override()
	public String obtenerFolderNumberByFolderId(String folderId) {
		OS2 os2 = this.os2Service.findByFolderId2(folderId);

		if (os2 != null) {
			return os2.getNumExpediente();
		} else {
			return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#findExpedienteByFolderId(java.lang
	 * .String)
	 */
	@Override()
	public OS2 findExpedienteByFolderId(String folderId) {

		return this.os2Service.findByFolderId(folderId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#getTerritorioExpedienteByFolderId
	 * (java.lang.String)
	 */
	@Override()
	public String getTerritorioExpedienteByFolderId(String folderId) {

		OS2 os2 = this.os2Service.findByFolderId2(folderId);
		return os2.getTeros2060();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#crearTramiteTareaSugerida(com.ejie
	 * .mbt.xml.Task, com.ejie.ab04b.model.Tarea)
	 */
	@Override()
	public TramiteProcedimiento crearTramiteTareaSugerida(Task task,
			Tarea tipoTarea) {

		// Obtenemos el expediente de os2s
		OS2 os2 = this.os2Service.findByFolderId(task.getFolderID());

		TramiteOS2 tramite = new TramiteOS2();
		tramite.setTipoTramite(tipoTarea.getTramite());
		tramite.setos2(os2);

		tramite = this.tramiteOS2sService.add(tramite);

		return tramite;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#crearTareaSugerida(com.ejie.mbt
	 * .xml.Task, com.ejie.ab04b.model.Tarea,
	 * com.ejie.ab04b.model.TramiteProcedimiento)
	 */
	@Override()
	public TareaProcedimiento crearTareaSugerida(Task task, Tarea tipoTarea,
			TramiteProcedimiento tramite) {

		TareaOS2 tarea = new TareaOS2();
		tarea.setTramiteOS2((TramiteOS2) tramite);
		tarea.setMailboxTaskId093(task.getMailboxTaskID());
		tarea.setTipoTarea(tipoTarea);
		tarea.setEstado093(EstadosTareas.SUGERIDA.getEstado());
		tarea.setFechaIni093(PlateaTramitacionUtils.getInstance()
				.parsearTimestampPlatea(task.getDoTimestamp()));

		ManejadorTareasOS2.LOGGER
				.error("################################ crearTareaSugerida = "
						+ task.getMailboxTaskID());

		tarea = this.tareaOS2Service.add(tarea);

		return tarea;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#crearExpediente(java.lang.String,
	 * com.ejie.foldermanagement.xml.ContextSubmissionEvent)
	 */
	@Override()
	public void crearExpediente(String sdetailInfo,
			ContextSubmissionEvent contextSubmission)
			throws AB04BParseException {

		/*
		 * DetailInfo detailInfo = DetailInfoParser.getInstance()
		 * .getDetailInfoAperturasSolTel(sdetailInfo);
		 */
		// TODO metemos folderId de prueba
		// contextSubmission.setFolderID("99999");
		/*
		 * this.os2Service .insertarOS2ContextSubmission(contextSubmission);
		 */
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#actualizarTareaEjecutada(com.ejie
	 * .mbt.xml.Task)
	 */
	@Override()
	public void actualizarTareaEjecutada(Task task) throws AB04BException {

		Tarea tipoTarea = this.tareaService.findByTaskIdProcedureId(
				task.getTaskID(), task.getProcedureID());
		OS2 os2 = this.os2Service.findByFolderId(task.getFolderID());

		if (tipoTarea == null) {
			throw new AB04BException("JMS Procesado antes de tiempo.");
		}

		if (tipoTarea.getEsInicial090() && TipoTareaPlatea.APERTURA.name()
				.equalsIgnoreCase(tipoTarea.getTaskId090())) {
			// try {
			// Thread.sleep(ConstantesNum.NUM_5000);
			// } catch (InterruptedException e) {
			// ManejadorTareasOS2.LOGGER.error(
			// "[ERROR] : Fallo en actualizarTareaEjecutada en sleep");
			// }
		} else {
			// try {
			// Thread.sleep(ConstantesNum.NUM_3000);
			// } catch (InterruptedException e) {
			// ManejadorTareasOS2.LOGGER.error(
			// "[ERROR] : Fallo en actualizarTareaEjecutada en sleep");
			// }
		}

		TareaOS2 tarea = this.tareaOS2Service
				.findByMailboxTaskId(task.getMailboxTaskID());
		tarea.setEstado093(EstadosTareas.EJECUTADA.getEstado());
		if (Constantes.AUTOMATICA.equals(tarea.getTipoTarea().getTipo090())
				&& !TipoTareaPlatea.APERTURA.name()
						.equalsIgnoreCase(tipoTarea.getTaskId090())) {

			tarea.setUsuario093(task.getSenderID());

		} else if (TipoTareaPlatea.APERTURA.name()
				.equalsIgnoreCase(tipoTarea.getTaskId090())) {
			tarea.setUsuario093(os2.getUsuarioApe060());
		}

		if (os2.getUsuarioTram060() == null && os2.getUsuarioApe060() != null) {
			tarea.setUsuario093(os2.getUsuarioApe060());
		} else {
			tarea.setUsuario093(os2.getUsuarioTram060());
		}

		if (!TipoTramiteFlujo.APERTURA.name().equalsIgnoreCase(
				tipoTarea.getTramite().getProceedingId089())) {
			if (TipoTramiteFlujo.REQUERIMIENTO.name().equalsIgnoreCase(
					tipoTarea.getTramite().getProceedingId089())
					&& "S".equals(os2.getDoccorrecta060())) {
				tarea.setUsuario093(os2.getUsuarioApe060());
			} else {
				tarea.setUsuario093(os2.getUsuarioTram060());
			}
		}
		// TODO la fecha endTimestamp no llega siempre. No sabemos por qué
		tarea.setFechaFin093(
				PlateaTramitacionUtils.getInstance()
						.parsearTimestampPlatea(task.getEndTimestamp() != null
								? task.getEndTimestamp()
								: task.getDoTimestamp()));

		this.tareaOS2Service.updateFilled(tarea);

		// Si es la tarea de cierre del expediente
		if (task.getTaskID().equals(TipoTareaFlujo.CIERRE.getTaskId())) {
			os2.setFecier060(new Date());
			os2.setEstado060(Constantes.ESTADO_CERRADO);
			this.os2Service.update(os2);
		} else if (TipoTramiteFlujo.REQUERIMIENTO.name().equalsIgnoreCase(
				tipoTarea.getTramite().getProceedingId089())) {
			os2.setFecreq060(new Date());
			os2.setFecsub060(null);
			this.os2Service.update(os2);
			this.os2Service.updateBatchSub(os2);
		}

		if (tipoTarea.getEsInicial090() && TipoTareaPlatea.APERTURA.name()
				.equalsIgnoreCase(tipoTarea.getTaskId090())) {
			os2.setEstado060("A");
			this.os2Service.updateFilled(os2);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#obtenerTramitePadreExistente(com
	 * .ejie.ab04b.model.Tarea, com.ejie.ab04b.model.ComunicacionProcedimiento)
	 */
	@Override()
	public TramiteProcedimiento obtenerTramitePadreExistente(Tarea tarea,
			ComunicacionProcedimiento comunicacion) {

		OS2 os2 = (OS2) comunicacion;

		return this.tramiteOS2sService.findLastTramiteByTipo(
				tarea.getTramite().getIdTramite089(), os2);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#ejecutarTareaAutomatica(com.ejie
	 * .ab04b.model.TareaProcedimiento)
	 */
	@Override()
	public void ejecutarTareaAutomatica(TareaProcedimiento tareaGenerica)
			throws AB04BException {
		try {
			TareaOS2 tarea = (TareaOS2) tareaGenerica;

			String taskId = tarea.getTipoTarea().getTaskId090();

			// Estas tareas vienen por aquí porque al adjuntar un documento, hay
			// una
			// transformación a PDFA (con espera), por lo que no podemos hacer
			// uso
			// de la etiqueta <processUrl> del flujo
			if (TipoTareaFlujo.ADJUNTAR_DOC_REQUERIMIENTO
					.esEquivalente(taskId)) {
				this.tramitacionOS2Service.prepararDocRequerimiento(tarea);

			} else if (TipoTareaFlujo.ACUSE_REQUERIMIENTO_POSTAL
					.esEquivalente(taskId)) {

				TramiteOS2 tramite = this.obtenerTramiteOS2(tarea);

				this.tramitacionOS2Service.tramitarAcuseRequerimiento(tarea,
						tramite);

			}

			tarea.setEstado093(EstadosTareas.INICIADA.getEstado());
			this.tareaOS2Service.updateFilled(tarea);
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.ab04b.evento.ManejadorTareas#
	 * continuarEjecucionTareaEsperaTransformacion(java.lang.Long,
	 * java.lang.Long)
	 */
	@Override()
	public void continuarEjecucionTareaEsperaTransformacion(Long idTarea,
			Long idDocumento) {

		TareaOS2 tarea = this.tareaOS2Service.find(new TareaOS2(idTarea));

		DocumentoOS2 documento = this.documentoOS2Service
				.find(new DocumentoOS2(idDocumento));

		// Antes de continuar, cambiamos el nombre al documento para ponerle
		// extensión PDF
		String extension = Utilities.getInstance()
				.obtenerExtensionFichero(documento.getNombreDoc094());
		if (extension != null) {
			String nomFichero = documento.getNombreDoc094();
			nomFichero = nomFichero.substring(0,
					nomFichero.length() - extension.length());
			nomFichero = nomFichero.concat(Constantes.EXT_PDF);
			documento.setNombreDoc094(nomFichero);

			this.documentoOS2Service.updateFilled(documento);
		}

		String taskId = tarea.getTipoTarea().getTaskId090();
		try {
			if (TipoTareaFlujo.ADJUNTAR_DOC_REQUERIMIENTO
					.esEquivalente(taskId)) {
				this.tramitacionOS2Service.tramitarAdjuntarDoc(tarea,
						documento);
			}
		} catch (Exception e) {
			ManejadorTareasOS2.LOGGER.error("ERROR EN MANEJADOR");
			e.getCause();
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#processEnviarNotificacion(com.ejie
	 * .mbt.xml.Task)
	 */
	@Override()
	public void processEnviarNotificacion(Task task) throws AB04BException {

		TareaOS2 tarea = null;

		try {

			int contador = 0;

			// intentamos 3 veces recuperar la solicitud por si no le ha dado
			// tiempo a guardar

			while (contador < 3 && tarea == null) {

				contador++;

				tarea = this.obtenerTareaOS2(task.getMailboxTaskID());

				if (tarea == null) {

					TimeUnit.SECONDS.sleep(2);

				}

			}

			if (contador == 3) {

				throw new AB04BException("No existe tarea con mailboxtaskid: "
						+ task.getMailboxTaskID());

			}
		} catch (Exception e) {
			throw new AB04BException("Error: " + e.getMessage());
		}

		TramiteOS2 tramite = this.obtenerTramiteOS2(tarea);

		TipoTramiteFlujo tipoTramite = TipoTramiteFlujo
				.valueOf(tramite.getTipoTramite().getProceedingId089());

		this.tramitacionOS2Service.processEnviarNotificacion(task, tramite,
				tarea, tipoTramite);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#processRegistrarComunicacionPostal
	 * (com.ejie.mbt.xml.Task)
	 */
	@Override()
	public void processRegistrarComunicacionPostal(Task task) throws Exception {

		TareaOS2 tarea = null;

		try {

			int contador = 0;

			// intentamos 3 veces recuperar la solicitud por si no le ha dado
			// tiempo a guardar

			while (contador < 3 && tarea == null) {

				contador++;

				tarea = this.obtenerTareaOS2(task.getMailboxTaskID());

				if (tarea == null) {

					TimeUnit.SECONDS.sleep(2);

				}

			}

			if (contador == 3) {

				throw new AB04BException("No existe tarea con mailboxtaskid: "
						+ task.getMailboxTaskID());

			}
		} catch (Exception e) {
			throw new AB04BException("Error: " + e.getMessage());
		}

		TramiteOS2 tramite = this.obtenerTramiteOS2(tarea);

		TipoTramiteFlujo tipoTramite = TipoTramiteFlujo
				.valueOf(tramite.getTipoTramite().getProceedingId089());

		this.tramitacionOS2Service.processRegistrarComunicacionPostal(task,
				tramite, tarea, tipoTramite);
	}

	/**
	 * Obtener tarea OS 2.
	 * 
	 * mailboxTaskId String TareaOS2
	 *
	 * @param mailboxTaskId
	 *            the mailbox task id
	 * @return the tarea OS 2
	 */
	private TareaOS2 obtenerTareaOS2(String mailboxTaskId) {

		return this.tareaOS2Service.findByMailboxTaskId(mailboxTaskId);
	}

	/**
	 * Obtener tramite OS 2.
	 * 
	 * tarea TareaOS2 TramiteOS2
	 *
	 * @param tarea
	 *            the tarea
	 * @return the tramite OS 2
	 */
	private TramiteOS2 obtenerTramiteOS2(TareaOS2 tarea) {

		TramiteOS2 tramite = this.tramiteOS2sService
				.find(tarea.getTramiteOS2());
		tramite.setTipoTramite(
				this.tramiteService.find(tramite.getTipoTramite()));

		return tramite;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#generarYObtenerIdTramiteApertura
	 * (com.ejie.foldermanagement.xml.ContextSubmissionEvent)
	 */
	@Override()
	public Long generarYObtenerIdTramiteApertura(
			ContextSubmissionEvent contextSubmission) throws AB04BException {
		//
		// try {
		// Thread.sleep(ConstantesNum.NUM_2000);
		// } catch (InterruptedException e) {
		// ManejadorTareasOS2.LOGGER.error(
		// "[ERROR] : Fallo en generarYObtenerIdTramiteApertura sleep");
		// }

		// Obtenemos la comunicación de os2s
		OS2 os2 = this
				.findExpedienteByFolderId(contextSubmission.getFolderID());

		if (os2 == null) {
			throw new AB04BException("JMS Procesado antes de tiempo.");
		}

		os2.setUsuarioApe060(contextSubmission.getRegistrySenderID());

		this.os2Service.updateUsuariosTramitacion(os2);

		// Obtenemos el tipo de trámite de os2
		Tramite tipoTramiteOS2 = this.tramiteService
				.findByProceedingIdProcedureId(TipoTramiteFlujo.APERTURA.name(),
						Utilities.getInstance().obtenerProcedureIdOs2());

		// Creamos el trámite de os2 para el expediente
		TramiteOS2 tramiteOS2 = new TramiteOS2();
		tramiteOS2.setNumRegistro092(contextSubmission.getRegistryNumber());
		try {
			tramiteOS2.setFecRegistro092(
					Utilities.getInstance().stringToDatePlatea(
							contextSubmission.getRegistryTimestamp()));
		} catch (Exception e) {
			ManejadorTareasOS2.LOGGER.error(
					"[ERROR] : Fallo en generarYObtenerIdTramiteApertura: contextSubmission.getRegistryTimestamp()");
		}
		tramiteOS2.setTipoTramite(tipoTramiteOS2);
		tramiteOS2.setos2(os2);
		tramiteOS2 = this.tramiteOS2sService.add(tramiteOS2);

		return tramiteOS2.getIdTramite092();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.evento.ManejadorTareas#guardarDocumentosSolicitud(com.
	 * ejie.foldermanagement.xml.DocumentsEvent, java.lang.String,
	 * java.lang.Long)
	 */
	@Override()
	public void guardarDocumentosSolicitud(DocumentsEvent documents,
			String fechaCreacion, Long idTramite) {

		this.documentoOS2Service.addDocumentosSolicitud(
				documents.getDocumentEvent(), fechaCreacion, idTramite);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ejie.ab04b.evento.ManejadorTareas#
	 * generarYObtenerIdTramiteYTareaAportacion
	 * (com.ejie.foldermanagement.xml.ContextSubmissionEvent)
	 */
	@Override()
	public Long generarYObtenerIdTramiteYTareaAportacion(
			ContextSubmissionEvent contextSubmission) {

		// Obtenemos la comunicación de os2s
		OS2 os2 = this
				.findExpedienteByFolderId(contextSubmission.getFolderID());

		os2.setFecsub060(new Date());
		this.os2Service.updateFecSub(os2);

		os2.setUsuarioAport060(contextSubmission.getRegistrySenderID());

		this.os2Service.updateUsuariosTramitacion(os2);

		// Mirar si se trata de una aportacion genérica o una subsanación
		String tipotramite = TipoTramiteFlujo.APORTACION_DOCUMENTACION.name();
		if (ConstantesPlateaTramitacion.SUBMISSIONTYPE_APORT_SUBSANA_OS2
				.equals(contextSubmission.getSubmissionType())) {
			tipotramite = TipoTramiteFlujo.SUBSANACION.name();
		}

		// Obtenemos el tipo de trámite de os2
		Tramite tipoTramiteOS2 = this.tramiteService
				.findByProceedingIdProcedureId(tipotramite,
						Utilities.getInstance().obtenerProcedureIdOs2());

		// Creamos el trámite de os2 para el expediente
		TramiteOS2 tramiteOS2 = new TramiteOS2();

		tramiteOS2.setNumRegistro092(contextSubmission.getRegistryNumber());
		try {
			tramiteOS2.setFecRegistro092(
					Utilities.getInstance().stringToDatePlatea(
							contextSubmission.getRegistryTimestamp()));
		} catch (Exception e) {
			ManejadorTareasOS2.LOGGER.error(
					"[ERROR] : Fallo en generarYObtenerIdTramiteYTareaAportacion: contextSubmission.getRegistryTimestamp()");
		}

		tramiteOS2.setTipoTramite(tipoTramiteOS2);
		tramiteOS2.setos2(os2);
		tramiteOS2 = this.tramiteOS2sService.add(tramiteOS2);

		// Obtenemos el tipo de trámite de os2
		Tarea tipoTarea = this.tareaService.findByTaskIdProcedureId(
				TipoTareaFlujo.SUBSANACION.getTaskId(),
				Utilities.getInstance().obtenerProcedureIdOs2());

		this.crearTareaEjecutada(tipoTarea, tramiteOS2, contextSubmission);

		return tramiteOS2.getIdTramite092();
	}

	/**
	 * Crear tarea ejecutada.
	 * 
	 * tipoTarea the tipo tarea tramite the tramite contextSubmission the
	 * context submission the tarea procedimiento
	 *
	 * @param tipoTarea
	 *            the tipo tarea
	 * @param tramite
	 *            the tramite
	 * @param contextSubmission
	 *            the context submission
	 * @return the tarea procedimiento
	 */
	private TareaProcedimiento crearTareaEjecutada(Tarea tipoTarea,
			TramiteProcedimiento tramite,
			ContextSubmissionEvent contextSubmission) {

		OS2 os2 = this
				.findExpedienteByFolderId(contextSubmission.getFolderID());

		TareaOS2 tarea = new TareaOS2();
		tarea.setTramiteOS2((TramiteOS2) tramite);
		tarea.setMailboxTaskId093("NO ES TAREA PLATEA");
		tarea.setTipoTarea(tipoTarea);
		tarea.setEstado093(EstadosTareas.EJECUTADA.getEstado());
		tarea.setFechaIni093(new Date());
		tarea.setFechaFin093(new Date());
		tarea.setUsuario093(os2.getUsuarioAport060());

		tarea = this.tareaOS2Service.add(tarea);

		return tarea;

	}

}
