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.DocumentoOS3;
import com.ejie.ab04b.model.OS3;
import com.ejie.ab04b.model.Tarea;
import com.ejie.ab04b.model.TareaOS3;
import com.ejie.ab04b.model.TareaProcedimiento;
import com.ejie.ab04b.model.Tramite;
import com.ejie.ab04b.model.TramiteOS3;
import com.ejie.ab04b.model.TramiteProcedimiento;
import com.ejie.ab04b.service.DocumentoOS3Service;
import com.ejie.ab04b.service.OS3Service;
import com.ejie.ab04b.service.TareaOS3Service;
import com.ejie.ab04b.service.TareaService;
import com.ejie.ab04b.service.TramiteOS3Service;
import com.ejie.ab04b.service.TramiteService;
import com.ejie.ab04b.service.tramitacion.TramitacionOS3Service;
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 = "manejadorTareasOS3")
public class ManejadorTareasOS3 implements ManejadorTareas {

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

	@Autowired()
	private OS3Service os3Service;
	@Autowired()
	private TramiteOS3Service tramiteOS3sService;
	@Autowired()
	private TareaOS3Service tareaOS3Service;
	@Autowired()
	private DocumentoOS3Service documentoOS3Service;
	@Autowired()
	private TramiteService tramiteService;

	@Autowired()
	private TramitacionOS3Service tramitacionOS3Service;

	@Autowired()
	private TareaService tareaService;

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

		return this.os3Service.findByFolderId(folderId).getDoccorrecta061();
	}

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

		OS3 os3 = this.os3Service.findByFolderId2(folderId);

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

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

		return this.os3Service.findByFolderId(folderId);
	}

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

		OS3 os3 = this.os3Service.findByFolderId2(folderId);
		return os3.getTeros3061();
	}

	/*
	 * (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 os3s
		OS3 os3 = this.os3Service.findByFolderId(task.getFolderID());

		TramiteOS3 tramite = new TramiteOS3();
		tramite.setTipoTramite(tipoTarea.getTramite());
		tramite.setOs3(os3);

		tramite = this.tramiteOS3sService.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) {

		TareaOS3 tarea = new TareaOS3();
		tarea.setTramiteOS3((TramiteOS3) tramite);
		tarea.setMailboxTaskId096(task.getMailboxTaskID());
		tarea.setTipoTarea(tipoTarea);
		tarea.setEstado096(EstadosTareas.SUGERIDA.getEstado());
		tarea.setFechaIni096(PlateaTramitacionUtils.getInstance()
				.parsearTimestampPlatea(task.getDoTimestamp()));

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

		tarea = this.tareaOS3Service.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.os3Service .insertarOS3ContextSubmission(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());

		OS3 os3 = this.os3Service.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) {
			// ManejadorTareasOS3.LOGGER.error(
			// "[ERROR] : Fallo en actualizarTareaEjecutada sleep");
			// }
		} else {
			// try {
			// Thread.sleep(ConstantesNum.NUM_3000);
			// } catch (InterruptedException e) {
			// ManejadorTareasOS3.LOGGER.error(
			// "[ERROR] : Fallo en actualizarTareaEjecutada en sleep");
			// }
		}

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

			tarea.setUsuario096(task.getSenderID());

		} else if (TipoTareaPlatea.APERTURA.name()
				.equalsIgnoreCase(tipoTarea.getTaskId090())) {
			tarea.setUsuario096(os3.getUsuarioApe061());
		}

		if (os3.getUsuarioTram061() == null && os3.getUsuarioApe061() != null) {
			tarea.setUsuario096(os3.getUsuarioApe061());
		} else {
			tarea.setUsuario096(os3.getUsuarioTram061());
		}

		if (!TipoTramiteFlujo.APERTURA.name().equalsIgnoreCase(
				tipoTarea.getTramite().getProceedingId089())) {
			if (TipoTramiteFlujo.REQUERIMIENTO.name().equalsIgnoreCase(
					tipoTarea.getTramite().getProceedingId089())
					&& "S".equals(os3.getDoccorrecta061())) {
				tarea.setUsuario096(os3.getUsuarioApe061());
			} else {
				tarea.setUsuario096(os3.getUsuarioTram061());
			}
		}
		// TODO la fecha endTimestamp no llega siempre. No sabemos por qué
		tarea.setFechaFin096(
				PlateaTramitacionUtils.getInstance()
						.parsearTimestampPlatea(task.getEndTimestamp() != null
								? task.getEndTimestamp()
								: task.getDoTimestamp()));

		this.tareaOS3Service.updateFilled(tarea);

		// Si es la tarea de cierre del expediente
		if (task.getTaskID().equals(TipoTareaFlujo.CIERRE.getTaskId())) {

			os3.setFecier061(new Date());
			os3.setEstado061(Constantes.ESTADO_CERRADO);
			this.os3Service.update(os3);
		} else if (TipoTramiteFlujo.REQUERIMIENTO.name().equalsIgnoreCase(
				tipoTarea.getTramite().getProceedingId089())) {
			os3.setFecreq061(new Date());
			os3.setFecsub061(null);
			this.os3Service.update(os3);
			this.os3Service.updateBatchSub(os3);
		}

		if (tipoTarea.getEsInicial090() && TipoTareaPlatea.APERTURA.name()
				.equalsIgnoreCase(tipoTarea.getTaskId090())) {
			os3.setEstado061("A");
			this.os3Service.updateFilled(os3);
		}

	}

	/*
	 * (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) {

		OS3 os3 = (OS3) comunicacion;

		return this.tramiteOS3sService.findLastTramiteByTipo(
				tarea.getTramite().getIdTramite089(), os3);
	}

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

			TareaOS3 tarea = (TareaOS3) 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.tramitacionOS3Service.prepararDocRequerimiento(tarea);

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

				TramiteOS3 tramite = this.obtenerTramiteOS3(tarea);

				this.tramitacionOS3Service.tramitarAcuseRequerimiento(tarea,
						tramite);

			}

			tarea.setEstado096(EstadosTareas.INICIADA.getEstado());
			this.tareaOS3Service.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) {

		TareaOS3 tarea = this.tareaOS3Service.find(new TareaOS3(idTarea));

		DocumentoOS3 documento = this.documentoOS3Service
				.find(new DocumentoOS3(idDocumento));

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

			this.documentoOS3Service.updateFilled(documento);
		}

		String taskId = tarea.getTipoTarea().getTaskId090();
		try {
			if (TipoTareaFlujo.ADJUNTAR_DOC_REQUERIMIENTO
					.esEquivalente(taskId)) {
				this.tramitacionOS3Service.tramitarAdjuntarDoc(tarea,
						documento);
			}
		} catch (Exception e) {
			ManejadorTareasOS3.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 {

		TareaOS3 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.obtenerTareaOS3(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());
		}

		TramiteOS3 tramite = this.obtenerTramiteOS3(tarea);

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

		this.tramitacionOS3Service.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 {

		TareaOS3 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.obtenerTareaOS3(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());
		}

		TramiteOS3 tramite = this.obtenerTramiteOS3(tarea);

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

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

	/**
	 * Obtener tarea OS 3.
	 * 
	 * mailboxTaskId String TareaOS3
	 *
	 * @param mailboxTaskId
	 *            the mailbox task id
	 * @return the tarea OS 3
	 */
	private TareaOS3 obtenerTareaOS3(String mailboxTaskId) {

		return this.tareaOS3Service.findByMailboxTaskId(mailboxTaskId);
	}

	/**
	 * Obtener tramite OS 3.
	 * 
	 * tarea TareaOS3 TramiteOS3
	 *
	 * @param tarea
	 *            the tarea
	 * @return the tramite OS 3
	 */
	private TramiteOS3 obtenerTramiteOS3(TareaOS3 tarea) {

		TramiteOS3 tramite = this.tramiteOS3sService
				.find(tarea.getTramiteOS3());
		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) {
		// ManejadorTareasOS3.LOGGER.error(
		// "[ERROR] : Fallo en generarYObtenerIdTramiteApertura sleep");
		// }

		// Obtenemos la comunicación de os3s
		OS3 os3 = this
				.findExpedienteByFolderId(contextSubmission.getFolderID());

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

		os3.setUsuarioApe061(contextSubmission.getRegistrySenderID());

		this.os3Service.updateUsuariosTramitacion(os3);

		// Obtenemos el tipo de trámite de os3
		Tramite tipoTramiteOS3 = this.tramiteService
				.findByProceedingIdProcedureId(TipoTramiteFlujo.APERTURA.name(),
						Utilities.getInstance().obtenerProcedureIdOs3());

		// Creamos el trámite de os3 para el expediente
		TramiteOS3 tramiteOS3 = new TramiteOS3();
		tramiteOS3.setNumRegistro095(contextSubmission.getRegistryNumber());
		try {
			tramiteOS3.setFecRegistro095(
					Utilities.getInstance().stringToDatePlatea(
							contextSubmission.getRegistryTimestamp()));
		} catch (Exception e) {
			ManejadorTareasOS3.LOGGER.error(
					"[ERROR] : Fallo en generarYObtenerIdTramiteApertura: contextSubmission.getRegistryTimestamp()");
		}
		tramiteOS3.setTipoTramite(tipoTramiteOS3);
		tramiteOS3.setOs3(os3);
		tramiteOS3 = this.tramiteOS3sService.add(tramiteOS3);

		return tramiteOS3.getIdTramite095();
	}

	/*
	 * (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.documentoOS3Service.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 os3s
		OS3 os3 = this
				.findExpedienteByFolderId(contextSubmission.getFolderID());

		os3.setFecsub061(new Date());
		this.os3Service.updateFecSub(os3);

		os3.setUsuarioAport061(contextSubmission.getRegistrySenderID());

		this.os3Service.updateUsuariosTramitacion(os3);

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

		// Obtenemos el tipo de trámite de os3
		Tramite tipoTramiteOS3 = this.tramiteService
				.findByProceedingIdProcedureId(tipotramite,
						Utilities.getInstance().obtenerProcedureIdOs3());

		// Creamos el trámite de os3 para el expediente
		TramiteOS3 tramiteOS3 = new TramiteOS3();

		tramiteOS3.setNumRegistro095(contextSubmission.getRegistryNumber());
		try {
			tramiteOS3.setFecRegistro095(
					Utilities.getInstance().stringToDatePlatea(
							contextSubmission.getRegistryTimestamp()));
		} catch (Exception e) {
			ManejadorTareasOS3.LOGGER.error(
					"[ERROR] : Fallo en generarYObtenerIdTramiteYTareaAportacion: contextSubmission.getRegistryTimestamp()");
		}

		tramiteOS3.setTipoTramite(tipoTramiteOS3);
		tramiteOS3.setOs3(os3);
		tramiteOS3 = this.tramiteOS3sService.add(tramiteOS3);

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

		this.crearTareaEjecutada(tipoTarea, tramiteOS3, contextSubmission);

		return tramiteOS3.getIdTramite095();
	}

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

		OS3 os3 = this
				.findExpedienteByFolderId(contextSubmission.getFolderID());

		TareaOS3 tarea = new TareaOS3();
		tarea.setTramiteOS3((TramiteOS3) tramite);
		tarea.setMailboxTaskId096("NO ES TAREA PLATEA");
		tarea.setTipoTarea(tipoTarea);
		tarea.setEstado096(EstadosTareas.EJECUTADA.getEstado());
		tarea.setFechaIni096(new Date());
		tarea.setFechaFin096(new Date());
		tarea.setUsuario096(os3.getUsuarioAport061());

		tarea = this.tareaOS3Service.add(tarea);

		return tarea;

	}

}
