package com.blueland.bpm.unitework;

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

import org.activiti.engine.delegate.event.BaseEntityEventListener;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.blueland.bpm.application.model.ApplicationEntity;
import com.blueland.bpm.application.service.ApplicationManager;
import com.blueland.bpm.common.util.ApplicationContextHolder;
import com.blueland.bpm.engine.config.model.SysGlType;
import com.blueland.bpm.engine.config.service.SysGlTypeManager;
import com.blueland.bpm.engine.core.model.ActivityInstanceModel;
import com.blueland.bpm.engine.core.model.ExceptionErrorCode;
import com.blueland.bpm.engine.core.model.ProcessInputModel;
import com.blueland.bpm.engine.core.model.ProcessInstanceModel;
import com.blueland.bpm.engine.core.model.ProcessInstanceModellBuilder;
import com.blueland.bpm.engine.core.service.ProcessConfigService;
import com.blueland.bpm.engine.util.ProcessDefinitionUtils;
import com.blueland.bpm.engine.util.WorkFlowContants;
import com.blueland.bpm.engine.util.WorkFlowException;
import com.blueland.unitework.model.UniteworkTask;

/**
 * 统一待办消息同步公共类
 * 
 * @version: 1.0
 * @author lw
 */
public abstract class TaskCommonEvent extends BaseEntityEventListener{
	public static final String UNITEWORK_CATEGORY_BANJIAN = "1";
	public static String UNITEWORK_DATA_SOURCE_BPM="BPM";
	protected Logger logger = LoggerFactory.getLogger(getClass());
	private static Map<String, ApplicationEntity> applications = new HashMap<String, ApplicationEntity>();

	/**
	 * 构造待办对象
	 * 
	 * @param processInfo
	 * @param nextActInst
	 * @return
	 */
	protected UniteworkTask buildUniteworkTaskByTodo(
			ProcessInstanceModel processInfo, ActivityInstanceModel nextActInst) {
		UniteworkTask unitework = buildUniteworkTask(processInfo, nextActInst);
		/*ProcessConfigService processConfigService = (ProcessConfigService) com.blueland.bpm.common.util.ApplicationContextHolder
				.getBean("processConfigServiceImpl");*/
		try {
			SysGlTypeManager sysGlTypeManager = (SysGlTypeManager) com.blueland.bpm.common.util.ApplicationContextHolder
					.getBean("sysGlTypeManager");
			SysGlType sysGlType = sysGlTypeManager
					.getSysGlTypeByprocessDefId(processInfo.getProcDefId());

			if (sysGlType != null
					&& StringUtils.isEmpty(unitework.getCategory())) {
				unitework.setCategory(sysGlType.getTypeId());
				unitework.setCategoryName(sysGlType.getTypeName());
			}
		} catch (Exception e) {
			logger.error("插入统一待办获取流程分类异常,unitework:"+unitework,e);
		}
		/*
		 * ProcessInfoConfig processInfoConfig = processConfigService
		 * .getProcessInfoConfig(processInfo.getProcDefId()); unitework
		 * .setOtherSysDealStatus(processInfoConfig != null &&
		 * String.valueOf(processInfoConfig .getOtherSysDealStatus()) != null ?
		 * String .valueOf(processInfoConfig.getOtherSysDealStatus()) : "0");
		 */
		//unitework.setOtherSysDealStatus("0");
		unitework.setStatus("1");
		return unitework;
	}
	/**
	 * 构造已办对象
	 * 
	 * @param processInfo
	 * @param nextActInst
	 * @return
	 */
	
	protected UniteworkTask buildUniteworkTaskByZaiban(
			ProcessInstanceModel processInfo) {
		ActivityInstanceModel curActInst = processInfo.getCurrentActivity();
		UniteworkTask unitework = buildUniteworkTask(processInfo, curActInst);
		unitework.setStatus("2");
		unitework.setId(curActInst.getActInstId());
		unitework.setDealTime(new Date());
		return unitework;
	}

	/**
	 * 获取已办ID
	 * 
	 * @param processInfo
	 * @return
	 */
	protected String getZaibanId(ProcessInstanceModel processInfo) {
		ActivityInstanceModel curActInst = processInfo.getCurrentActivity();
		return curActInst.getActInstId();
	}

	/**
	 * 构造通用Unitework对象
	 * 
	 * @param processInfo
	 * @param actInst
	 * @return
	 */
	protected UniteworkTask buildUniteworkTask(ProcessInstanceModel processInfo,
			ActivityInstanceModel actInst) {
		ProcessInputModel processInputModel=processInfo.getProcessInputModel();
		
		UniteworkTask unitework = new UniteworkTask();
		unitework.setTitle(actInst.getProcTitle());
		unitework.setAbstract(actInst.getProcTitle());
		unitework.setContent(actInst.getProcTitle());
		if(StringUtils.isNotEmpty(processInputModel.getWf_uniteCategory())){
			unitework.setCategory(processInputModel.getWf_uniteCategory());
		}
		String appId=processInputModel.getWf_appId();
		if(StringUtils.isEmpty(appId)){
			appId="bpm";
		}
		unitework.setTenantId(appId);
		unitework.setTenantName("bpm");
		//unitework.setSendTime(new Date());

		unitework.setSendTime(actInst.getCreateTime()!=null?actInst.getCreateTime():new Date());
		unitework.setSendUserId(actInst.getSender());
		unitework.setSendUserName(actInst.getSendUserName());
		unitework.setSendOrgId(actInst.getSenderOrgId());
		unitework.setSendOrgName(actInst.getSenderOrgName());
		unitework.setRecUserId(actInst.getReceiver());
		unitework.setRecUserName(actInst.getReceiverUserName());
		unitework.setRecOrgId(actInst.getReceiverOrgId());
		unitework.setRecOrgName(actInst.getReceiverOrgName());
		unitework.setStartUserId(processInfo.getStartUserId());
		unitework.setStartUserName(processInfo.getStartUserName());
		unitework.setStartOrgId(processInfo.getStarterOrgId());
		unitework.setStartOrgName(processInfo.getStarterOrgName());
		unitework.setStartTime(processInfo.getCreateTime());
		if(StringUtils.isNoneEmpty(processInputModel.getWf_parentProcInstId())){
			unitework.setParentProcInstId(processInputModel.getWf_parentProcInstId());
		}else{
			unitework.setParentProcInstId(processInfo.getParentProcInstId());
		}
		unitework.setTopProcInstId(processInfo.getTopProcInstId());
		unitework.setProcInstId(processInfo.getProcInstId());
		unitework.setCurActDefId(actInst.getActDefId());
		unitework.setCurActDefName(actInst.getActDefName());
		unitework.setCurActInstId(actInst.getActInstId());
		unitework.setDataSource(UNITEWORK_DATA_SOURCE_BPM);
		unitework.setPrevActDefId(actInst.getPrevActDefId());
		unitework.setPrevActDefName(actInst.getPrevActDefName());
		unitework.setPrevActInstId(actInst.getPrevActInstId());
		unitework.setProcDefId(actInst.getProcDefId());
		unitework.setProcDefKey(processInfo.getProcessDefinition().getProcDefKey());
		unitework.setProcDefName(actInst.getProcDefName());
		unitework.setBatchId(processInputModel.getWf_batchId());
		initPortalURL(unitework,processInputModel,actInst.getProcDefId(),actInst.getActDefId());
		return unitework;
	}


	protected ProcessInstanceModel buildProcessInstanceModel(
			TaskEntity delegateTask) {
		ProcessInstanceModellBuilder processInstanceModellBuilder = (ProcessInstanceModellBuilder) com.blueland.bpm.common.util.ApplicationContextHolder
				.getBean("processInstanceModellBuilder");
		ProcessInputModel processInputModel =ProcessDefinitionUtils.getWfprocessInputModel(delegateTask);
		ProcessInstanceModel processInstanceModel = processInstanceModellBuilder
				.builderProcessInfoNoNextTask(processInputModel,(ProcessDefinition) delegateTask.getExecution().getProcessDefinition(), delegateTask.getProcessInstance(),
						(org.activiti.engine.task.Task) delegateTask);
		return processInstanceModel;
	}
	
	protected ProcessInstanceModel buildProcessInstanceModel(
			TaskEntity delegateTask,ExecutionEntity executionEntity ) {
		ProcessInstanceModellBuilder processInstanceModellBuilder = (ProcessInstanceModellBuilder) com.blueland.bpm.common.util.ApplicationContextHolder
				.getBean("processInstanceModellBuilder");
		ProcessInputModel processInputModel =ProcessDefinitionUtils.getWfprocessInputModel(executionEntity
				.getVariables() != null ? executionEntity.getVariables()
						: executionEntity.getParent().getVariables());
		ProcessInstanceModel processInstanceModel = processInstanceModellBuilder
				.builderProcessInfoNoNextTask(processInputModel,(ProcessDefinition)  delegateTask.getExecution().getProcessDefinition(),
						delegateTask.getProcessInstance(),
						(org.activiti.engine.task.Task) delegateTask);
		return processInstanceModel;
	}
	
	private static String convertUrl(UniteworkTask unitework,String uniteworkUrl){
		if(StringUtils.isEmpty(uniteworkUrl)){
			return "";
		}
		String prefix="&";
		if(uniteworkUrl.indexOf("?")==-1){
			prefix="?";
		}
		String url= uniteworkUrl+prefix+"topProcInstId="+unitework.getTopProcInstId()+"&procInstId="+unitework.getProcInstId()+"&actInstId="+unitework.getCurActInstId();
		if(StringUtils.isNotEmpty(unitework.getBatchId())){
			url+="&batchId="+unitework.getBatchId();
		}
		return url;
	}
	
	public boolean isSendESB(TaskEntity delegateTask){
		if(!WorkFlowContants.ACTION_TYPE_LAUCH_PROCESS.equals(delegateTask.getActionType())&&!WorkFlowContants.ACTION_TYPE_SAVE_ACTIVITY.equals(delegateTask.getActionType())){
			return true;
		}
		boolean isStartUserTask=ProcessDefinitionUtils.isStartUserTask(delegateTask);
		if(isStartUserTask){
			return false;
		}
		return true;
	}
	
	private static void initPortalURL(UniteworkTask unitework,ProcessInputModel processInputModel,String procDefId,String curActDefId) {
		//首先获取流程配置的url做为应用统一待办路径
		ProcessConfigService processConfigService=(ProcessConfigService) com.blueland.bpm.common.util.ApplicationContextHolder.getBean("processConfigServiceImpl");
		Map<String,String> portalMap=processConfigService.getPortalPage(procDefId, curActDefId);
		if(StringUtils.isEmpty(processInputModel.getWf_uniteworkUrl())) {
			String curl=(String) portalMap.get("curl");
			unitework.setUrl(convertUrl(unitework,curl));
		}else{
			unitework.setUrl(convertUrl(unitework,processInputModel.getWf_uniteworkUrl()));
		}
		if(StringUtils.isEmpty(processInputModel.getWf_cportalProtocol())){
			String cprotocol=(String) portalMap.get("cprotocol");
			unitework.setCportalProtocol(cprotocol);
		}else{
			unitework.setCportalProtocol(processInputModel.getWf_cportalProtocol());
		}
		if(StringUtils.isEmpty(processInputModel.getWf_mportalUrl())) {
			String murl=(String) portalMap.get("murl");
			unitework.setMportalUrl(convertUrl(unitework,murl));
		}else{
			unitework.setMportalUrl(convertUrl(unitework,processInputModel.getWf_mportalUrl()));
		}
		if(StringUtils.isEmpty(processInputModel.getWf_mportalProtocol())){
			String mprotocol=(String) portalMap.get("mprotocol");
			unitework.setMportalProtocol(mprotocol);
		}else{
			unitework.setMportalProtocol(processInputModel.getWf_mportalProtocol());
		}
		if(StringUtils.isEmpty(processInputModel.getWf_otherSysDealStatus())){
			String mreadonly=(String) portalMap.get("mreadonly");
			unitework.setOtherSysDealStatus(mreadonly);
		}else{
			unitework.setOtherSysDealStatus(processInputModel.getWf_otherSysDealStatus());
		}
		//如果流程/环节/接口都没有值，那么给Protocol默认值
		if(StringUtils.isEmpty(unitework.getMportalProtocol())){
			unitework.setMportalProtocol("none");
		}
		//如果流程/环节/接口都没有值，那么给Protocol默认值
		if(StringUtils.isEmpty(unitework.getCportalProtocol())){
			unitework.setCportalProtocol("hnzy:workitem");
		}
		if(StringUtils.isEmpty(unitework.getUrl())){
			throw new WorkFlowException(ExceptionErrorCode.C3000,"统一待办URL为空");
		}
	}
	private static void initUniteworkURL(UniteworkTask unitework,ProcessInputModel processInputModel,String procDefId,String curActDefId) {
		if(StringUtils.isEmpty(processInputModel.getWf_uniteworkUrl())) {
			//首先获取流程配置的url做为应用统一待办路径
			ProcessConfigService processConfigService=(ProcessConfigService) com.blueland.bpm.common.util.ApplicationContextHolder.getBean("processConfigServiceImpl");
			String wfPageUrl=processConfigService.getWorkflowPage(procDefId, curActDefId);
			if(StringUtils.isNotEmpty(wfPageUrl)){
				processInputModel.setWf_uniteworkUrl(wfPageUrl);
				return ;
			}
			//获取应用的统一待办路径
			ApplicationEntity app = applications.get(processInputModel.getWf_appId());
			if(app == null) {
				ApplicationManager applicationManager = (ApplicationManager)ApplicationContextHolder.getBean("applicationManager");
				app = applicationManager.getById(processInputModel.getWf_appId());
			}
			if( app != null) {
				applications.put(processInputModel.getWf_appId(), app);
				processInputModel.setWf_uniteworkUrl(app.getAppAccessUrl());
			}else {
				throw new WorkFlowException(ExceptionErrorCode.B2050,"统一待办URL为空");
			}
		}
		unitework.setCportalProtocol(processInputModel.getWf_cportalProtocol());
		String uniteworkUrl=convertUrl(unitework,processInputModel.getWf_uniteworkUrl());
		unitework.setUrl(uniteworkUrl);
	}
}
