package com.fp.bpmlib.task;

import java.util.Date;
import java.util.Map;

import javax.naming.InitialContext;

import org.jbpm.services.task.exception.PermissionDeniedException;
import org.jbpm.services.task.utils.OnErrorAction;
import org.jbpm.services.task.wih.AbstractHTWorkItemHandler;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.runtime.process.WorkItem;
import org.kie.api.runtime.process.WorkItemManager;
import org.kie.api.task.model.Task;
import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext;
import org.kie.internal.task.api.InternalTaskService;
import org.kie.internal.task.api.model.ContentData;
import org.kie.internal.task.exception.TaskException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fp.bpmlib.ejb.local.JbpmBeanLocal;
import com.fp.bpmlib.query.monitor.FlowActivitySave;
import com.fp.simple.dto.TaskInfo;

public class MaiaWorkItemHandler extends AbstractHTWorkItemHandler {

	private static final Logger logger = LoggerFactory.getLogger(MaiaWorkItemHandler.class);
	private RuntimeManager runtimeManager;

	public RuntimeManager getRuntimeManager() {
		return runtimeManager;
	}

	public void setRuntimeManager(RuntimeManager runtimeManager) {
		this.runtimeManager = runtimeManager;
	}

	public MaiaWorkItemHandler() {
	}

	@SuppressWarnings("unchecked")
	private void fillRuntimeManager(WorkItem workItem) {
		try {
	        JbpmBeanLocal local = (JbpmBeanLocal) new InitialContext().lookup("java:global/maiaear-2.1/bpmlib/jbpmbean");
	        runtimeManager = local.getRuntimeManager();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
		// JVC obtiene runtimemanager por base de conocimiento y adiciona fecha de vencimiento de la tarea.
		this.fillRuntimeManager(workItem);

		RuntimeEngine runtime = runtimeManager.getRuntimeEngine(ProcessInstanceIdContext.get(workItem.getProcessInstanceId()));
		KieSession ksessionById = runtime.getKieSession();

		Task task = this.createTaskBasedOnWorkItemParams(ksessionById, workItem);

		ContentData content = this.createTaskContentBasedOnWorkItemParams(ksessionById, workItem);
		try {
			long taskId = ((InternalTaskService) runtime.getTaskService()).addTask(task, content);
			if (this.isAutoClaim(workItem, task)) {
				runtime.getTaskService().claim(taskId, (String) workItem.getParameter("SwimlaneActorId"));
			}
			// JVC crea un registro en TbpmTareas.
			this.createTbpmActivities(taskId, workItem, task);

		} catch (Exception e) {
			if (action.equals(OnErrorAction.ABORT)) {
				manager.abortWorkItem(workItem.getId());
			} else if (action.equals(OnErrorAction.RETHROW)) {
				if (e instanceof RuntimeException) {
					throw (RuntimeException) e;
				} else {
					throw new RuntimeException(e);
				}
			} else if (action.equals(OnErrorAction.LOG)) {
				StringBuilder logMsg = new StringBuilder();
				logMsg.append(new Date()).append(": Error when creating task on task server for work item id ").append(workItem.getId());
				logMsg.append(". Error reported by task server: ").append(e.getMessage());
				logger.error(logMsg.toString(), e);
				// rethrow to cancel processing if the exception is not recoverable
				if (!(e instanceof TaskException) || ((e instanceof TaskException) && !((TaskException) e).isRecoverable())) {
					if (e instanceof RuntimeException) {
						throw (RuntimeException) e;
					} else {
						throw new RuntimeException(e);
					}
				}
			}
		}
	}


	@SuppressWarnings("unchecked")
	private void createTbpmActivities(long idtarea, WorkItem workItem, Task task) throws Exception {
		Map<String, Object> mparam = (Map<String, Object>) workItem.getParameters().get("maia");
		TaskInfo taskInfo = (TaskInfo)workItem.getParameters().get("taskMetaData");
//		String usuario = task.getTaskData().getActualOwner() == null ? null : task.getTaskData().getActualOwner().getId();//usuario responsable
		// crea tbpmtareas con los datos de la tarea.
		FlowActivitySave.crearActivity(mparam, taskInfo,idtarea,task.getTaskData().getCreatedOn());
		//
	}

	@Override
	public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
		RuntimeEngine runtime = runtimeManager.getRuntimeEngine(ProcessInstanceIdContext.get(workItem.getProcessInstanceId()));
		Task task = runtime.getTaskService().getTaskByWorkItemId(workItem.getId());
		if (task != null) {
			try {
				runtime.getTaskService().exit(task.getId(), "Administrator");
			} catch (PermissionDeniedException e) {
				logger.info(e.getMessage());
			}
		}

	}

}
