package com.artfess.activiti.ext.listener;


import com.artfess.activiti.def.BpmDefUtil;
import com.artfess.base.util.AppUtil;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.StringUtil;
import com.artfess.base.util.time.TimeUtil;
import com.artfess.bpm.api.cmd.BaseActionCmd;
import com.artfess.bpm.api.constant.BpmConstants;
import com.artfess.bpm.api.constant.EventType;
import com.artfess.bpm.api.constant.ProcessInstanceStatus;
import com.artfess.bpm.api.constant.ScriptType;
import com.artfess.bpm.api.context.ContextThreadUtil;
import com.artfess.bpm.api.model.delegate.BpmDelegateExecution;
import com.artfess.bpm.api.model.process.inst.BpmProcessInstance;
import com.artfess.bpm.engine.inst.DefaultProcessInstCmd;
import com.artfess.bpm.engine.task.cmd.DefaultTaskFinishCmd;
import com.artfess.bpm.persistence.manager.BpmCheckOpinionManager;
import com.artfess.bpm.persistence.manager.BpmCustomSignDataManager;
import com.artfess.bpm.persistence.manager.BpmExeStackManager;
import com.artfess.bpm.persistence.manager.BpmProcessInstanceManager;
import com.artfess.bpm.persistence.manager.BpmSignDataManager;
import com.artfess.bpm.persistence.model.BpmExeStack;
import com.artfess.bpm.persistence.model.DefaultBpmCheckOpinion;
import com.artfess.bpm.persistence.model.DefaultBpmProcessInstance;
import com.artfess.bpm.persistence.model.DefaultBpmTask;
import com.artfess.bpm.util.BpmCheckOpinionUtil;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 流程结束监听事件。
 * <pre>
 * 描述：流程结束监听事件。
 * 构建组：x5-bpmx-activiti
 * 作者：ray
 * 邮箱:zhangyg@jee-soft.cn
 * 日期:2014-3-20-下午5:05:10
 * 版权：广州宏天软件有限公司版权所有
 * </pre>
 */
public class EndEventListener extends AbstractExecutionListener {

	/**
	 * serialVersionUID
	 * @since 1.0.0
	 */
	private static final long serialVersionUID = -9011829013817237607L;

	@Resource
	BpmProcessInstanceManager bpmProcessInstanceManager;
	@Resource
	BpmCheckOpinionManager bpmCheckOpinionManager;
	@Resource
	BpmSignDataManager bpmSignDataManager;
	@Resource
	BpmCustomSignDataManager bpmCustomSignDataManager;



	@Override
	public EventType getBeforeTriggerEventType() {
		return EventType.END_EVENT;
	}

	@Override
	public EventType getAfterTriggerEventType() {
		return EventType.END_POST_EVENT;
	}

	@Override
	public void beforePluginExecute(BpmDelegateExecution bpmDelegateExecution) {
	}

	@Override
	public void triggerExecute(BpmDelegateExecution execution) {
		//更新流程实例状态。
		updProcessInstance(execution);

		Integer instCount=(Integer) execution.getSupperVariable(BpmConstants.NUMBER_OF_INSTANCES);
		Integer completeInstCount=(Integer) execution.getSupperVariable(BpmConstants.NUMBER_OF_COMPLETED_INSTANCES);
		//外部子流程的情况需要传递变量。
		//外部子流程结束时构建CMD。
		if(StringUtil.isNotZeroEmpty(execution.getSupperExecutionId())){
			//单实例的情况。//多实例结束
			if(instCount==null || instCount.equals(completeInstCount)){
				Map<String,Object> commuVars_=execution.getVariables();
				Map<String, Object> commuVars = ContextThreadUtil.getCommuVars();
				commuVars_.putAll(commuVars);
				ContextThreadUtil.setCommuVars(commuVars_);

				String parentProcInstId=(String) commuVars_.get(BpmConstants.PROCESS_PARENT_INST_ID);

				BpmDelegateExecution supperExecution = execution.getSupperExecution();
				// 外部子流程结束后  可以直来直往回到原来的驳回的节点
				if(BeanUtils.isNotEmpty(supperExecution)){
					String destination = getDestination(parentProcInstId,supperExecution.getNodeId(),ContextThreadUtil.getActionCmd());
					if(StringUtil.isNotEmpty(destination)){
						BpmDefUtil.prepare(supperExecution.getBpmnDefId(), supperExecution.getNodeId(), new String[]{destination});
					}
				}

				converCmd(parentProcInstId);
			}
		}
//		//获得流程实例ID
//		String bpmnInstId=bpmDelegateExecution.getBpmnInstId();
//
//		//不是有效状态 或 当前的excutionId和主线程不相同时，直接返回
//		if(!bpmDelegateExecution.isEnded()
//				|| !bpmDelegateExecution.getExecutionEntityId().equals(bpmnInstId)){
//			return;
//		}
//		//发布流程结束事件。
//		ProcessInstanceEndEvent ev=new ProcessInstanceEndEvent(bpmDelegateExecution);
//
//		BpmDelegateExecution execution=(BpmDelegateExecution) ev.getSource();
		//		//发布流程结束事件。
//		ProcessInstanceEndEvent event=new ProcessInstanceEndEvent(bpmDelegateExecution);
//        //todo 添加license4eip7 包后会导致审批不了任务
//		ProcessInstEndListener bean = AppUtil.getBean(ProcessInstEndListener.class);
//		AppUtil.publishEvent(event);

	}

	@Override
	public void afterPluginExecute(BpmDelegateExecution bpmDelegateExecution) {
	}

	@Override
	protected ScriptType getScriptType() {
		return ScriptType.END;
	}

	/**
	 * 转换CMD。
	 * @param parentProcInstId
	 * void
	 */
	private void converCmd(String parentProcInstId){
		BaseActionCmd baseCmd=(BaseActionCmd)ContextThreadUtil.getActionCmd();

		BpmProcessInstance parentProcessInst=bpmProcessInstanceManager.get(parentProcInstId);
		DefaultProcessInstCmd cmd=new DefaultProcessInstCmd();
		cmd.setInstId(parentProcInstId);
		cmd.setActionName(baseCmd.getActionName());
		cmd.setBpmIdentities(baseCmd.getBpmIdentities());
		cmd.addTransitVars(BpmConstants.PROCESS_INST,parentProcessInst);
		cmd.addTransitVars(BpmConstants.BPM_TASK, baseCmd.getTransitVars(BpmConstants.BPM_TASK));
		cmd.addTransitVars(BpmConstants.PREVIOUS_CMD,baseCmd);
		ContextThreadUtil.setActionCmd(cmd);
	}

	/**
	 *
	 *更新流程实例状态。
	 * @param execution
	 * void
	 */
	private void updProcessInstance(BpmDelegateExecution execution){
		String instId=(String) execution.getVariable(BpmConstants.PROCESS_INST_ID);
		BaseActionCmd cmd=(BaseActionCmd)ContextThreadUtil.getActionCmd();
		DefaultBpmProcessInstance instance= bpmProcessInstanceManager.get(instId);
		String procInstId = instance.getId();

		//添加多一个结束的审核意见记录
		DefaultBpmCheckOpinion entity= BpmCheckOpinionUtil.buildBpmCheckOpinion(execution,instId,true);
		DefaultBpmTask task =(DefaultBpmTask) cmd.getTransitVars(BpmConstants.BPM_TASK);
		if (BeanUtils.isNotEmpty(task)) {
			entity.setParentTaskId(task.getTaskId());
		}
		bpmCheckOpinionManager.create(entity);

		//将审批意见归档为历史，并删除流程实例的审批意见
		bpmCheckOpinionManager.archiveHistory(procInstId);

		//更新流程实例状态
		updateStatus(instance, cmd.getActionName());

		//和流程实例保持一致了，都不使用历史表.以免实例结束流程图没有节点状态
		//bpmProStatusManager.archiveHistory(procInstId);

		//流程结束时，清除会签结果数据。
		List<String> instList=new ArrayList<String>();
		instList.add(procInstId);
		bpmSignDataManager.delByInstList(instList);
		//流程结束时，清除bpm_custom_signdata相关数据。
		bpmCustomSignDataManager.removeByInstId(procInstId);
	}

	private void updateStatus(DefaultBpmProcessInstance instance, String actionName){
		instance.setStatus(ProcessInstanceStatus.STATUS_END.getKey());
		instance.setDuration(getDuration(instance.getCreateTime()));
		instance.setResultType(actionName);
		instance.setEndTime(LocalDateTime.now());
		bpmProcessInstanceManager.update(instance);
	}

	private Long getDuration(LocalDateTime localDateTime){
		Long duration= TimeUtil.getTime(LocalDateTime.now(), localDateTime);
		return duration;
	}

	public int getOrder() {
		return 1;
	}

	private String getDestination(String instId, String nodeId, Object transitVars) {
		BpmExeStackManager bpmExeStackManager = AppUtil.getBean(BpmExeStackManager.class);
		BpmExeStack stack = bpmExeStackManager.getStack(instId, nodeId, null);
		if(BeanUtils.isNotEmpty(stack) && StringUtil.isNotEmpty(stack.getTargetNode())){
			DefaultTaskFinishCmd cmd = (DefaultTaskFinishCmd) transitVars;
			cmd.setDestination(stack.getTargetNode());
			return stack.getTargetNode();
		}
		return "";
	}


}
