package com.ejie.ad74a.jms.service;

import java.util.Map;

import org.joda.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.ad74a.jms.util.MessageParser;
import com.ejie.ad74a.tareas.service.TareaAbrirPlazoService;
import com.ejie.ad74a.tareas.service.TareaAcuseNotificacionService;
import com.ejie.ad74a.tareas.service.TareaAperturaService;
import com.ejie.ad74a.tareas.service.TareaAportarDocumentacionService;
import com.ejie.ad74a.tareas.service.TareaCierreService;
import com.ejie.ad74a.tareas.service.TareaComunicacionInformeService;
import com.ejie.ad74a.tareas.service.TareaEstudioService;
import com.ejie.ad74a.tareas.service.TareaNotificacionService;
import com.ejie.ad74a.tareas.service.TareaPasoDesistimientoService;
import com.ejie.ad74a.tareas.service.TareaSolicitudInformeIntervencionService;
import com.ejie.ad74a.util.constantes.Constantes;
import com.ejie.ad74a.util.constantes.EstadoNotificacionEnum;
import com.ejie.ad74a.util.constantes.TareasEnum;
import com.ejie.ad74a.ws.client.platea.model.notification.NotificationBody;
import com.ejie.ad74a.ws.client.platea.model.task.Task;

/**
 * EntidadesServiceImpl generated by UDA, 21-jul-2021 10:42:45.
 * 
 * @author UDA
 */

@Service(value = "taskJMSService")
public class TaskJMSServiceImpl implements TaskJMSService {

	private static final Logger logger = LoggerFactory.getLogger(TaskJMSServiceImpl.class);

	private static final int TRANSACTION_TIMEOUT = 60;

	@Autowired
	private TareaAperturaService tareaAperturaService;

	@Autowired
	private TareaEstudioService tareaEstudioService;

	@Autowired
	private TareaAbrirPlazoService tareaAbrirPlazoService;

	@Autowired
	private TareaNotificacionService tareaNotificacionService;

	@Autowired
	private TareaAportarDocumentacionService tareaAportarDocumentacionService;

	@Autowired
	private TareaAcuseNotificacionService tareaAcuseNotificacionService;

	@Autowired
	private TareaPasoDesistimientoService tareaPasoDesistimientoService;

	@Autowired
	private TareaCierreService tareaCierreService;

	@Autowired
	private TareaComunicacionInformeService tareaComunicacionInformeService;

	@Autowired
	private TareaSolicitudInformeIntervencionService tareaSolicitudInformeIntervencionService;

	/**
	 * Gestión del evento de Tareas - R02_TASK
	 */
	@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class, timeout = TaskJMSServiceImpl.TRANSACTION_TIMEOUT)
	public void tratamientoTask(NotificationBody notificationBody, Map<String, Object> mapaMensaje) throws Throwable {
		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratamientoTask - Inicio");

		// Estado de la tarea
		String strStatus = (String) mapaMensaje.get("Status");

		MessageParser<Task> parserTask = new MessageParser<Task>(Task.class.getPackage().getName());
		Task task = parserTask.parse(notificationBody.getXmlValue().get(0));

		if (Constantes.EventTask.EVENT_R02_TASK_STATUS_SUGERIDA.equals(strStatus)) {
			// **** TAREA SUGERIDA ****//
			TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratamientoTask - Tarea sugerida");
			this.tratarEventoTareaSugerida(task, mapaMensaje);
		} else if (Constantes.EventTask.EVENT_R02_TASK_STATUS_EJECUTADA.equals(strStatus)) {
			// **** TAREA EJECUTADA****//
			this.tratarEventoTareaEjecutada(task, mapaMensaje);
			TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratamientoTask - Tarea ejecutada");
		} else if (notificationBody != null
				&& (Constantes.EventTask.EVENT_R02_TASK_STATUS_RECHAZADA.equals(strStatus))) {
			// **** TAREA RECHAZADA / CANCELADA****//
			this.tratarEventoTareaCancelada(task, mapaMensaje);
			TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratamientoTask - Tarea rechazada/cancelada");
		}

		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratamientoTask - Fin");
	}

	/**
	 * Gestión del evento de Tarea Sugerida
	 * 
	 * @param task        Task con toda la información de la tarea sugerida
	 * @param mapaMensaje Map<String, Object> con las propiedades del evento
	 * @throws Throwable
	 */
	private void tratarEventoTareaSugerida(Task task, Map<String, Object> mapaMensaje) throws Throwable {
		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratarEventoTareaSugerida - inicio ");

		// Tipo de Tarea Platea
		String idTipoTareaPlatea = task.getTaskID();
		TaskJMSServiceImpl.logger
				.info("TaskJMSServiceImpl.tratarEventoTareaSugerida - idTipoTareaPlatea: " + idTipoTareaPlatea);

		switch ((TareasEnum.getEnumByTaskId(idTipoTareaPlatea))) {
		// ** TAREA APERTURA ** //
		case APERTURA:
			/****/
			this.tareaAperturaService.tareaSugerida(task);
			break;

		// ** Especificar acciones propias en función del tipo de tarea ** //
		// *****************************************************
		case ESTUDIO:
			/****/
			this.tareaEstudioService.tareaSugerida(task);
			break;
		case APER_PLAZO_RECUR_DESIS:
		case APER_PLAZO_DESIS:
			/****/
			this.tareaAbrirPlazoService.tareaSugerida(task);
			break;
		case RESOL_DESISTIMIENTO:
		case RESOL_CONCESION:
		case RESOL_DENEGACION:
		case RESOL_DENEGACION_SERVICIO_AUDIENCIA:
		case APOR_CARTA_LIQUID:
			/****/
			this.tareaAportarDocumentacionService.tareaSugerida(task, true);
			break;
		case ADJUNTAR_DOCUMENTACION:
		case REQUERIMIENTO_SUBSANACION:
		case AUDIENCIA:
			/****/
			this.tareaAportarDocumentacionService.tareaSugerida(task, false);
			break;

		// ** TAREAS NOTIFICACION ** //
		case NOTI_RESOL_DESISTIMIENTO:
		case NOTIFICACION_SUBSANACION:
		case NOTI_RESOL_CONCESION:
		case NOTI_RESOL_DENEGACION:
		case NOTI_TRAMITE_AUDIENCIA:
		case NOTI_RESOL_DENEGACION_SERVICIO_AUDIENCIA:
		case NOTI_LIQUIDACION:
			/****/
			this.tareaNotificacionService.tareaSugerida(task);
			break;

		// ** TAREAS ACUSE **//
		case ACUSE_NOTI_RESOL_DESIS:
		case ACUSENOTIFICACION_SUBSANA:
		case ACUSE_NOTI_RESOL_CONCESION:
		case ACUSE_NOTI_RESOL_DENEGACION:
		case ACUSE_NOTI_TRAMITE_AUDIENCIA:
		case ACUSE_DENEGACION_SERVICIO_AUDIENCIA:
		case ACUSE_NOTI_LIQUIDACION:
			/****/
			this.tareaAcuseNotificacionService.tareaSugerida(task);
			break;
		case PASO_DESISTIMIENTO:
			/****/
			this.tareaPasoDesistimientoService.tareaSugerida(task);
			break;

		case CIERRE:
			/****/
			this.tareaCierreService.tareaSugerida(task);
			break;
		case SOLICITUD_INFORME_INTERVENCION:
			/****/
			this.tareaSolicitudInformeIntervencionService.tareaSugerida(task);
			break;
		case COMUNICACION_INFORME:
			/****/
			this.tareaComunicacionInformeService.tareaSugerida(task);
			break;
		default:
			break;
		}

		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratarEventoTareaSugerida - fin ");
	}

	/**
	 * Gestión del evento de Tarea Ejecutada
	 * 
	 * @param task        Task con toda la información de la tarea sugerida
	 * @param mapaMensaje Map<String, Object> con las propiedades del evento
	 * @throws Throwable
	 */
	private void tratarEventoTareaEjecutada(Task task, Map<String, Object> mapaMensaje) throws Throwable {
		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratarEventoTareaEjecutada - inicio ");

		// Tipo de Tarea Platea
		String idTipoTareaPlatea = task.getTaskID();
		TaskJMSServiceImpl.logger
				.info("TaskJMSServiceImpl.tratarEventoTareaEjecutada - idTareaPlatea: " + idTipoTareaPlatea);

		// ** Especificar acciones propias en función del tipo de tarea ** //
		// *****************************************************

		switch ((TareasEnum.getEnumByTaskId(idTipoTareaPlatea))) {
		// ** TAREA APERTURA ** //
		case APERTURA:
			/****/
			this.tareaAperturaService.tareaEjecutada(task);
			break;

		// ** TAREAS ESTUDIO **//
		case ESTUDIO:
			/****/
			this.tareaEstudioService.tareaEjecutada(task);
			break;

		// ** TAREAS APERTURA DE PLAZOS **//
		case APER_PLAZO_RECUR_DESIS:
		case APER_PLAZO_DESIS:
			/****/
			this.tareaAbrirPlazoService.tareaEjecutada(task);
			break;
		case RESOL_DESISTIMIENTO:
		case RESOL_CONCESION:
		case RESOL_DENEGACION:
		case RESOL_DENEGACION_SERVICIO_AUDIENCIA:
		case APOR_CARTA_LIQUID:

			/****/
			this.tareaAportarDocumentacionService.tareaEjecutada(task, true);
			break;

		case REQUERIMIENTO_SUBSANACION:
		case ADJUNTAR_DOCUMENTACION:
		case AUDIENCIA:
			/****/
			this.tareaAportarDocumentacionService.tareaEjecutada(task, false);
			break;
		// ** TAREAS NOTIFICACION ** //
		case NOTI_RESOL_DESISTIMIENTO:
		case NOTIFICACION_SUBSANACION:
		case NOTI_RESOL_CONCESION:
		case NOTI_RESOL_DENEGACION:
		case NOTI_TRAMITE_AUDIENCIA:
		case NOTI_RESOL_DENEGACION_SERVICIO_AUDIENCIA:
		case NOTI_LIQUIDACION:
			/****/
			this.tareaNotificacionService.tareaEjecutada(task);
			break;

		// ** TAREAS ACUSE **//
		case ACUSE_NOTI_RESOL_DESIS:
		case ACUSENOTIFICACION_SUBSANA:
		case ACUSE_NOTI_RESOL_CONCESION:
		case ACUSE_NOTI_RESOL_DENEGACION:
		case ACUSE_NOTI_TRAMITE_AUDIENCIA:
		case ACUSE_DENEGACION_SERVICIO_AUDIENCIA:
		case ACUSE_NOTI_LIQUIDACION:
			/****/
			this.tareaAcuseNotificacionService.tareaEjecutada(task);
			break;

		// ** PASO A DESISTIMIENTO ** //
		case PASO_DESISTIMIENTO:
			/****/
			this.tareaPasoDesistimientoService.tareaEjecutada(task);
			break;
		case CIERRE:
			/****/
			this.tareaCierreService.tareaEjecutada(task);
			break;
		case SOLICITUD_INFORME_INTERVENCION:
			/****/
			this.tareaSolicitudInformeIntervencionService.tareaEjecutada(task);
			break;
		case COMUNICACION_INFORME:
			/****/
			this.tareaComunicacionInformeService.tareaEjecutada(task);
			break;
		default:
			break;
		}

		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratarEventoTareaEjecutada - Fin ");
	}

	/**
	 * Gestión del evento de Tarea Rechazada/Cancelada
	 * 
	 * @param task        Task con toda la información de la tarea sugerida
	 * @param mapaMensaje Map<String, Object> con las propiedades del evento
	 * @throws Throwable
	 */
	private void tratarEventoTareaCancelada(Task task, Map<String, Object> mapaMensaje) throws Throwable {
		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratarEventoTareaCancelada - inicio ");

		// Tipo de Tarea Platea
		String idTipoTareaPlatea = task.getTaskID();
		TaskJMSServiceImpl.logger
				.info("TaskJMSServiceImpl.tratarEventoTareaCancelada - idTipoTareaPlatea: " + idTipoTareaPlatea);

		// ** Procesos específicos por tipo de tarea **//
		switch ((TareasEnum.getEnumByTaskId(idTipoTareaPlatea))) {

		case REQUERIMIENTO_SUBSANACION:
			this.tareaAportarDocumentacionService.tareaCancelada(task);
			break;
		// ** Especificar acciones propias en función del tipo de tarea ** //
		// *****************************************************
		case ACUSENOTIFICACION_SUBSANA:
		case ACUSE_NOTI_TRAMITE_AUDIENCIA:
		case ACUSE_NOTI_RESOL_DESIS:
		case ACUSE_NOTI_RESOL_CONCESION:
		case ACUSE_NOTI_RESOL_DENEGACION:
		case ACUSE_DENEGACION_SERVICIO_AUDIENCIA:
			this.tareaAcuseNotificacionService.tareaEjecutada(task);
			break;

		case ESTUDIO:
			this.tareaEstudioService.tareaCancelada(task);
			break;
		default:
			break;
		}

		TaskJMSServiceImpl.logger.info("TaskJMSServiceImpl.tratarEventoTareaCancelada - fin ");
	}

}
