package com.artfess.bpm.listener;

import com.artfess.base.exception.WorkFlowException;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.StringUtil;
import com.artfess.bpm.api.cmd.ActionCmd;
import com.artfess.bpm.api.cmd.TaskFinishCmd;
import com.artfess.bpm.api.constant.AopType;
import com.artfess.bpm.api.constant.BpmConstants;
import com.artfess.bpm.api.event.DoNextEvent;
import com.artfess.bpm.api.event.DoNextModel;
import com.artfess.bpm.api.model.process.def.NodeProperties;
import com.artfess.bpm.api.model.process.inst.BpmProcessInstance;
import com.artfess.bpm.api.model.process.nodedef.BpmNodeDef;
import com.artfess.bpm.api.model.process.task.BpmTask;
import com.artfess.bpm.api.service.BpmDefinitionAccessor;
import com.artfess.bpm.api.service.BpmInstService;
import com.artfess.bpm.engine.task.cmd.DefaultTaskFinishCmd;
import com.artfess.bpm.persistence.manager.BpmProcessInstanceManager;
import com.artfess.bpm.persistence.manager.BpmTaskManager;
import com.artfess.bpm.persistence.model.DefaultBpmProcessInstance;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;



/**
 * 负责表单数据保存。
 * <pre>
 * 构建组：x5-bpmx-core
 * 作者：ray
 * 邮箱:zhangyg@jee-soft.cn
 * 日期:2014-9-4-下午5:52:30
 * 版权：广州宏天软件有限公司版权所有
 * </pre>
 */
@Service
public class DoNextEventListener  implements ApplicationListener<DoNextEvent>,Ordered {
	@Resource
	BpmProcessInstanceManager bpmProcessInstanceManager;
	@Resource
	BpmTaskManager bpmTaskManager;
	@Resource
	BpmDefinitionAccessor bpmDefinitionAccessor;
	@Resource
	BpmInstService bpmInstService;



	@Override
	public int getOrder() {
		return 1;
	}

	@Override
	public void onApplicationEvent(DoNextEvent ev) {
		DoNextModel model= (DoNextModel) ev.getSource();

		//设置业务主键。
		setBuinessKey(model);

		if(AopType.PREVIOUS.equals(model.getAopType())){
			try {
				before(model);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		else{
			try {
				after(model);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
	}

	/**
	 * 将主键放到上下文中。
	 * <pre>
	 *  适用情况，iframe的情况。
	 *  1.直接启动流程是businessKey为空。
	 *  2.在保存草稿的时候从实例中获取主键，放到cmd中。
	 *  	在编写处理器时，可以根据这个值判断到底增加数据还是更新数据。
	 * </pre>
	 * @param model
	 */
	private void setBuinessKey(DoNextModel model) {
		ActionCmd cmd = model.getTaskFinishCmd();

		if (!(cmd instanceof TaskFinishCmd)) return;

		DefaultBpmProcessInstance inst = (DefaultBpmProcessInstance) cmd.getTransitVars(BpmConstants.PROCESS_INST);

		if (!ActionCmd.DATA_MODE_PK.equals(inst.getDataMode())) return;

		String pkInst=inst.getBizKey();
		if(StringUtil.isNotEmpty(pkInst)){
			cmd.setBusinessKey(pkInst);
			cmd.setSysCode(inst.getSysCode());
		}
	}

	private void before(DoNextModel model) throws Exception{
		//检查流程实例是否禁用
		checkFlowIsValid(model);
		saveBusLink(model);
		executeHandler(model,true);
	}

	//检查流程实例是否禁用
	private void checkFlowIsValid(DoNextModel model) {
		BpmTask bpmTask = (BpmTask) model.getTaskFinishCmd().getTransitVars(BpmConstants.BPM_TASK);
		boolean isForbindden = bpmInstService.isSuspendByInstId(bpmTask.getProcInstId());
		if(isForbindden){
			throw new WorkFlowException("流程已经被禁止，请联系管理员！");
		}
	}

	private void saveBusLink(DoNextModel model) throws Exception{
		DefaultTaskFinishCmd cmd=(DefaultTaskFinishCmd) model.getTaskFinishCmd();
		ActionCmd actionCmd=(ActionCmd)cmd;
		BpmProcessInstance instance= (BpmProcessInstance) actionCmd.getTransitVars(BpmConstants.PROCESS_INST);
		//数据模式
		String dataMode=instance.getDataMode();

		if(ActionCmd.DATA_MODE_PAIR.equals(dataMode)){
			BusDataUtil.handExt(cmd);
		}
		//bo数据的处理
		else if (ActionCmd.DATA_MODE_BO.equals(dataMode)){
			BusDataUtil.handSaveBoData(instance, actionCmd);
		}
		else if (ActionCmd.DATA_MODE_PK.equals(dataMode)){

		}
	}


	private void after(DoNextModel model) throws Exception{
		executeHandler(model,false);
	}



	private NodeProperties getNodeProperties(DoNextModel model) throws Exception{
		ActionCmd cmd= (ActionCmd) model.getTaskFinishCmd();

		BpmTask bpmTask= (BpmTask) cmd.getTransitVars(BpmConstants.BPM_TASK);

		BpmProcessInstance instance= (BpmProcessInstance) cmd.getTransitVars(BpmConstants.PROCESS_INST);

		String nodeId=bpmTask.getNodeId();

		String defId=instance.getProcDefId();

		BpmNodeDef bpmNodeDef=bpmDefinitionAccessor.getBpmNodeDef(defId, nodeId);

		NodeProperties nodeProperties=null;

		if(StringUtil.isNotZeroEmpty(instance.getParentInstId())){
			BpmProcessInstance parentInst=bpmProcessInstanceManager.get(instance.getParentInstId());
			if (BeanUtils.isEmpty(bpmNodeDef)) {
				bpmNodeDef = bpmDefinitionAccessor.getBpmNodeDef(parentInst.getProcDefId(), nodeId);
			}
			String defKey=parentInst.getProcDefKey();
			nodeProperties=bpmNodeDef.getPropertiesByParentDefKey(defKey);
		}

		if(nodeProperties==null){
			nodeProperties=bpmNodeDef.getLocalProperties();
		}

		return nodeProperties;
	}


	private void executeHandler(DoNextModel model,boolean isBefore) throws Exception{
		TaskFinishCmd cmd= model.getTaskFinishCmd();

		ActionCmd actionCmd=(ActionCmd)cmd;

		//获取发起节点获取不到则获取第一个节点。
		NodeProperties properties= getNodeProperties(model);

		BusDataUtil.executeHandler(properties, actionCmd, isBefore);

	}
}
