/**
 * 
 */
package com.ejie.ab61.adaptadores.service;

import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.ejie.ab61.clientesWS.X43TareasTramitacion.AExtensionPoint;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TBoolean;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TGatTaskFilter;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TMessageFilterValueList;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TMessageList;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TMessageStatusList;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TMessageTipology;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TMessageTipologyList;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TNotificationBody;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TPersonIDName;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TStringList;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TTask;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.TTaskType;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.X43RTA;
import com.ejie.ab61.clientesWS.X43TareasTramitacion.X43RTAPortType;
import com.ejie.ab61.comun.Constantes;
import com.ejie.ab61.exceptions.X43TareasTramitacionException;
import com.ejie.ab61.comun.utilidades.config.Config;
//import com.ejie.ab61.utils.exceptions.UDAException;

/**
 *  
 * 
 */
@Service(value = "X43TareasTramitacionServiceImpl")
public class X43TareasTramitacionServiceImpl implements X43TareasTramitacionService {

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

	private X43RTA service;

	private static final QName qname = new QName("com/ejie/x43s/v2/rta/ws", "X43RTA");

	/**
	 * 
	 * @return X43RTAPortType
	 */
	private X43RTAPortType getX43TareasTramitacionServicePort() {
		return this.getX43TareasTramitacionServicePort(true);
	}

	/**
	 * 
	 * @param getPort
	 *            boolean
	 * 
	 * @return X43RTAPortType
	 */
	private X43RTAPortType getX43TareasTramitacionServicePort(boolean getPort) {
		try {
			Properties prop = Config.loadProperties(Constantes.FICHERO_CONFIGURACION);

			if (this.service == null) {

				// Creamos el servicio
				X43TareasTramitacionServiceImpl.logger
						.info("Antes de coger la URL del config URL_WS_X43TareasTramitacion ");
				this.service = new X43RTA(new URL(prop.getProperty("URL_WS_X43TareasTramitacion")),
						X43TareasTramitacionServiceImpl.qname);
				X43TareasTramitacionServiceImpl.logger
						.info("despies de coger la URL del config URL_WS_X43TareasTramitacion ");
				// definimos un handler cliente
				this.service.setHandlerResolver(new HandlerResolver() {
					@SuppressWarnings(value = { "unchecked", "rawtypes" })
					public List getHandlerChain(PortInfo portInfo) {
						return Collections.singletonList(new X43TareasTramitacionServiceHandler());
					}
				});

				X43TareasTramitacionServiceImpl.logger.info(
						"getX43TareasTramitacionServicePort. Dentro de creaci�n del servicio - Definido el handler");
			}
			if (getPort) {

				X43TareasTramitacionServiceImpl.logger
						.info("getX43TareasTramitacionServicePort. Antes de obtener el proxy");

				X43RTAPortType proxy = this.service.getX43RTAPort();

				X43TareasTramitacionServiceImpl.logger
						.info("getX43TareasTramitacionServicePort. Despues de obtener el proxy");

				Map<String, Object> ctxt = ((BindingProvider) proxy).getRequestContext();

				X43TareasTramitacionServiceImpl.logger
						.info("getX43TareasTramitacionServicePort. Despues de obtener el contexto");

				ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, prop.getProperty("URL_WS_X43TareasTramitacion"));

				X43TareasTramitacionServiceImpl.logger.info("getX43TareasTramitacionServicePort. Cargado el contexto");

				return proxy;
			}

		} catch (Exception e) {

			X43TareasTramitacionServiceImpl.logger
					.info("getX43TareasTramitacionServicePort. Excepcionnnn:" + e.getMessage());

			this.service = null;
		}
		return null;
	}

	/**
	 * Obtiene la lista de tareas aplicacando los filtros indicados
	 * 
	 * @param groupIDList
	 *            TStringList
	 * @param messageTipologyList
	 *            TMessageTipologyList
	 * @param statusList
	 *            TMessageStatusList
	 * @param mapProperties
	 *            TMessageFilterValueList
	 * @param iFirst
	 *            Integer
	 * @param iLast
	 *            Integer
	 * @param filter
	 *            TGatTaskFilter
	 * @param ep
	 *            AExtensionPoint
	 * @return TMessageList
	 * @throws X43TareasTramitacionException
	 *             X43TareasTramitacionException
	 */

	public TMessageList getGATTasks(TStringList groupIDList, TMessageTipologyList messageTipologyList,
			TMessageStatusList statusList, TMessageFilterValueList mapProperties, Integer iFirst, Integer iLast,
			TGatTaskFilter filter, AExtensionPoint ep) throws X43TareasTramitacionException, Exception {
		try {

			return this.getX43TareasTramitacionServicePort().getGATTasks(groupIDList, messageTipologyList, statusList,
					mapProperties, iFirst, iLast, filter, ep);

		} catch (X43TareasTramitacionException e) {
			throw e;
		} catch (Exception e_obtenerDocDokusi) {
			X43TareasTramitacionServiceImpl.logger.error("X43TareasTramitacionServiceImpl.getGATTasks",
					e_obtenerDocDokusi);
			// throw new UDAException("error.platea.invocation", true,
			// e_obtenerDocDokusi);
			throw e_obtenerDocDokusi;
		} finally {
			X43TareasTramitacionServiceImpl.logger.info("X43TareasTramitacionServiceImpl.getGATTasks - Final");
		}
	}

	/**
	 * Envio de una nueva tarea al buzon
	 * 
	 * @param notificationBody
	 *            TNotificationBody
	 * @param eventTypology
	 *            TMessageTipology
	 * @param ep
	 *            AExtensionPoint
	 * @return TBoolean
	 * @throws X43TareasTramitacionException
	 *             X43TareasTramitacionException
	 */

	public TBoolean addTask(TNotificationBody notificationBody, TMessageTipology eventTypology, AExtensionPoint ep)
			throws X43TareasTramitacionException, Exception {
		try {

			return this.getX43TareasTramitacionServicePort().addTask(notificationBody, eventTypology, ep);

		} catch (X43TareasTramitacionException e) {
			throw e;
		} catch (Exception e_obtenerDocDokusi) {
			X43TareasTramitacionServiceImpl.logger.error("X43TareasTramitacionServiceImpl.addTask", e_obtenerDocDokusi);
			// throw new UDAException("error.platea.invocation", true,
			// e_obtenerDocDokusi);
			throw e_obtenerDocDokusi;
		} finally {
			X43TareasTramitacionServiceImpl.logger.info("X43TareasTramitacionServiceImpl.addTask - Final");
		}
	}

	/**
	 * Devuelve la informaci�n necesaria para poder generar el documento
	 * ejgvDocument de cada tipo de tarea indicado en el par�metro taskType.
	 * 
	 * @param taskType
	 *            TTaskType
	 * @param taskGUID
	 *            String
	 * @param ep
	 *            AExtensionPoint
	 * @return TTask
	 * @throws X43TareasTramitacionException
	 *             X43TareasTramitacionException
	 */

	public TTask prepareTask(TTaskType taskType, String taskGUID, AExtensionPoint ep)
			throws X43TareasTramitacionException, Exception {
		try {

			return this.getX43TareasTramitacionServicePort().prepareTask(taskType, taskGUID, ep);

		} catch (X43TareasTramitacionException e) {
			throw e;
		} catch (Exception e_obtenerDocDokusi) {
			X43TareasTramitacionServiceImpl.logger.error("X43TareasTramitacionServiceImpl.prepareTask",
					e_obtenerDocDokusi);
			// throw new UDAException("error.platea.invocation", true,
			// e_obtenerDocDokusi);
			throw e_obtenerDocDokusi;
		} finally {
			X43TareasTramitacionServiceImpl.logger.info("X43TareasTramitacionServiceImpl.prepareTask - Final");
		}
	}

	/**
	 * Genera una tarea nueva.
	 * 
	 * @param procedureId
	 *            String
	 * @param folderId
	 *            String
	 * @param proceedingId
	 *            String
	 * @param taskId
	 *            String
	 * @param senderId
	 *            TPersonIDName
	 * @param ep
	 *            AExtensionPoint
	 * @return TBoolean
	 * @throws X43TareasTramitacionException
	 *             X43TareasTramitacionException
	 */

	public TBoolean prepareNewTask(String procedureId, String folderId, String proceedingId, String taskId,
			TPersonIDName senderId, AExtensionPoint ep) throws X43TareasTramitacionException, Exception {
		X43TareasTramitacionServiceImpl.logger.error("Inicio prepareNewTask");
		try {
			return this.getX43TareasTramitacionServicePort().prepareNewTask(procedureId, folderId, proceedingId, taskId,
					senderId, null, ep);
		} catch (X43TareasTramitacionException e) {
			e.printStackTrace();
			throw e;
		} catch (Exception e_prepareNewTask) {
			e_prepareNewTask.printStackTrace();
			X43TareasTramitacionServiceImpl.logger.error("X43TareasTramitacionServiceImpl.prepareNewTask",
					e_prepareNewTask);
			// throw new UDAException("error.platea.invocation", true,
			// e_prepareNewTask);
			throw e_prepareNewTask;
		} finally {
			X43TareasTramitacionServiceImpl.logger.info("X43TareasTramitacionServiceImpl.prepareNewTask - Final");
		}
	}

	/**
	 * Asigna tareas a un usuario.
	 * 
	 * @param taskGUIDList
	 *            TStringList
	 * @param mailboxID
	 *            String
	 * @param ep
	 *            AExtensionPoint
	 * @return TBoolean
	 * @throws X43TareasTramitacionException
	 *             X43TareasTramitacionException
	 */

	public TBoolean assignTasks(TStringList taskGUIDList, String mailboxID, AExtensionPoint ep)
			throws X43TareasTramitacionException, Exception {
		try {
			return this.getX43TareasTramitacionServicePort().assignTasks(taskGUIDList, mailboxID, ep);
		} catch (X43TareasTramitacionException e) {
			e.printStackTrace();
			throw e;
		} catch (Exception e_assignTasks) {
			e_assignTasks.printStackTrace();
			X43TareasTramitacionServiceImpl.logger.error("X43TareasTramitacionServiceImpl.assignTasks", e_assignTasks);
			// throw new UDAException("error.platea.invocation", true,
			// e_assignTasks);
			throw e_assignTasks;
		} finally {
			X43TareasTramitacionServiceImpl.logger.info("X43TareasTramitacionServiceImpl.assignTasks - Final");
		}
	}

	/**
	 * Ejecuta una tarea,
	 * 
	 * @param taskType
	 *            TTaskType
	 * @param task
	 *            TTask
	 * @param ep
	 *            AExtensionPoint
	 * @return TTask
	 * @throws X43TareasTramitacionException
	 *             X43TareasTramitacionException
	 */

	public TTask doTask(TTaskType taskType, TTask task, AExtensionPoint ep)
			throws X43TareasTramitacionException, Exception {
		try {

			return this.getX43TareasTramitacionServicePort().doTask(taskType, task, ep);

		} catch (X43TareasTramitacionException e) {
			e.printStackTrace();
			throw e;
		} catch (Exception e_obtenerDocDokusi) {
			e_obtenerDocDokusi.printStackTrace();
			X43TareasTramitacionServiceImpl.logger.error("X43TareasTramitacionServiceImpl.doTask", e_obtenerDocDokusi);
			// throw new UDAException("error.platea.invocation", true,
			// e_obtenerDocDokusi);
			throw e_obtenerDocDokusi;
		} finally {
			X43TareasTramitacionServiceImpl.logger.info("X43TareasTramitacionServiceImpl.doTask - Final");
		}
	}

}
