package com.blueland.bpm.engine.core.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.NativeHistoricProcessInstanceQuery;
import org.activiti.engine.history.NativeHistoricTaskInstanceQuery;
import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.blueland.bpm.engine.core.model.ActivityDefinitionModel;
import com.blueland.bpm.engine.core.model.ActivityInstanceModel;
import com.blueland.bpm.engine.core.model.BusinessDataObject;
import com.blueland.bpm.engine.core.model.ExceptionErrorCode;
import com.blueland.bpm.engine.core.model.ProcessInstanceModel;
import com.blueland.bpm.engine.core.model.ProcessLogModel;
import com.blueland.bpm.engine.core.power.RejectButActivityOperatePower;
import com.blueland.bpm.engine.core.service.AbstractServiceHelper;
import com.blueland.bpm.engine.core.service.ProcessDefinitionService;
import com.blueland.bpm.engine.core.service.ProcessInstanceService;
import com.blueland.bpm.engine.core.service.ProcessModelService;
import com.blueland.bpm.engine.core.service.ProcessTransitionFreeService;
import com.blueland.bpm.engine.util.PageFieldsUtil;
import com.blueland.bpm.engine.util.ProcessModelUtils;
import com.blueland.bpm.engine.util.WorkFlowContants;
import com.blueland.bpm.engine.util.WorkFlowException;
import com.blueland.bpm.identity.UserService;

/**
 * 流程实例Service
 * 
 * @version: 1.0
 * @author lw
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = false)
public class ProcessInstanceServiceImpl extends AbstractServiceHelper implements
		ProcessInstanceService {
	@Autowired
	private UserService userService;
	@Autowired
	protected ProcessDefinitionService processDefinitionService;
	@Autowired
	protected ProcessModelService processModelService;
	@Autowired
	RejectButActivityOperatePower rejectButActivityOperatePower;
	protected Logger logger = LoggerFactory.getLogger(getClass());

	public ActivityInstanceModel getTaskEntity(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			return null;
		}
		TaskEntity task = (TaskEntity) taskService.createTaskQuery()
				.taskId(taskId).singleResult();
		if (task == null) {
			return null;
		}
		return ActivityInstanceModel.buildAndActDef(
				task,
				processDefinitionService.getActivity(
						task.getProcessDefinitionId(),
						task.getTaskDefinitionKey()));
	}

	public ActivityInstanceModel getTask(String taskId) {
		Task task = this.findTaskById(taskId);
		ActivityDefinitionModel activityDefinitionModel = processDefinitionService
				.getActivity(task.getProcessDefinitionId(),
						task.getTaskDefinitionKey());
		if (activityDefinitionModel == null) {
			throw new WorkFlowException(ExceptionErrorCode.B2003,
					"activityDefinitionModel is not found");
		}
		return ActivityInstanceModel.buildAndActDef((TaskEntity) task,
				activityDefinitionModel);
	}

	public ActivityInstanceModel getHistoryTask(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			return null;
		}
		HistoricTaskInstance task = this.historyService
				.createHistoricTaskInstanceQuery().taskId(taskId)
				.singleResult();
		if (task == null) {
			return null;
		}
		return ActivityInstanceModel.buildAndActDef(
				task,
				processDefinitionService.getActivity(
						task.getProcessDefinitionId(),
						task.getTaskDefinitionKey()));
	}

	public ProcessInstanceModel getProcessInstanceById(String procInstId) {
		if (StringUtils.isEmpty(procInstId))
			return null;
		HistoricProcessInstance hisInstance = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(procInstId).singleResult();
		if (hisInstance != null)
			return ProcessInstanceModel.build(hisInstance);
		return null;
	}

	@Override
	public ProcessInstanceModel getProcessInstanceByBizKey(String bizKey)
			throws WorkFlowException {
		ProcessInstanceModel processInstanceModel = null;
		if (StringUtils.isEmpty(bizKey))
			return processInstanceModel;
		HistoricProcessInstance hisInstance = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceBusinessKey(bizKey).singleResult();
		if (hisInstance != null)
			processInstanceModel = ProcessInstanceModel.build(hisInstance);
		return processInstanceModel;
	}

	@Override
	public List<ProcessInstanceModel> getProcessInstancesByBizKey(String bizKey)
			throws WorkFlowException {
		List<ProcessInstanceModel> processInstanceModels = new ArrayList<ProcessInstanceModel>();
		if (StringUtils.isEmpty(bizKey))
			return processInstanceModels;
		List<HistoricProcessInstance> hisInstances = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceBusinessKey(bizKey)
				.orderByProcessInstanceStartTime().desc().list();
		if (hisInstances == null) {
			return processInstanceModels;
		}
		for (HistoricProcessInstance historicProcessInstance : hisInstances) {
			ProcessInstanceModel processInstanceModel = ProcessInstanceModel
					.build(historicProcessInstance);
			processInstanceModels.add(processInstanceModel);
		}
		return processInstanceModels;
	}


	@Override
	public Map<String, Object> getProcessInstanceVariables(
			String processInstanceId) throws WorkFlowException {
		if (StringUtils.isEmpty(processInstanceId)) {
			return null;
		}
		Map<String, Object> variables = new HashMap<String, Object>();
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).includeProcessVariables()
				.singleResult();
		if (processInstance != null) {
			variables = processInstance.getProcessVariables();
		} else {
			HistoricProcessInstance hisProcessInstance = historyService
					.createHistoricProcessInstanceQuery()
					.processInstanceId(processInstanceId)
					.includeProcessVariables().singleResult();
			if (hisProcessInstance != null)
				variables = hisProcessInstance.getProcessVariables();
		}
		return variables;
	}

	public Map<String, Object> getTaskVariables(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			return null;
		}
		return taskService.getVariables(taskId);
	}

	public Map<String, Object> getHistoryTaskVariables(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			return null;
		}
		HistoricTaskInstance historicTaskInstance = this.historyService
				.createHistoricTaskInstanceQuery().taskId(taskId)
				.includeTaskLocalVariables().singleResult();
		return historicTaskInstance.getTaskLocalVariables();
	}

	public Map<String, Object> getTaskFieldVariables(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			return null;
		}
		String variables = (String) taskService.getVariable(taskId,
				WorkFlowContants.WF_FIELDS_KEY);
		Map<String, Object> fieldsMap = PageFieldsUtil.fieldsToMap(variables);
		return fieldsMap;
	}

	public String getTaskFieldVariable(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			return null;
		}
		String fields = (String) taskService.getVariable(taskId,
				WorkFlowContants.WF_FIELDS_KEY);
		return fields;
	}

	public BusinessDataObject getBusinessDataObject(String procInstId) {
		if (StringUtils.isEmpty(procInstId)) {
			return null;
		}
		return (BusinessDataObject) getProcessInstanceVariables(procInstId)
				.get("wf_businessDataObject");
	}

	public String getProcessFieldVariable(String procInstId) {
		String fields = "";
		if (StringUtils.isEmpty(procInstId)) {
			return fields;
		}
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery().processInstanceId(procInstId)
				.includeProcessVariables().singleResult();
		Map<String, Object> variables = processInstance.getProcessVariables();
		if (variables.containsKey(WorkFlowContants.WF_FIELDS_KEY)) {
			// fieldsMap=PageFieldsUtil.fieldsToMap((String)variables.get("fields"));
			fields = (String) variables.get(WorkFlowContants.WF_FIELDS_KEY);
		}
		return fields;
	}

	public String getProcessFieldVariableByFinished(String procInstId) {
		String fields = "";
		if (StringUtils.isEmpty(procInstId)) {
			return fields;
		}
		HistoricProcessInstance processInstance = this.historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(procInstId).includeProcessVariables()
				.singleResult();
		Map<String, Object> variables = processInstance.getProcessVariables();
		if (variables.containsKey(WorkFlowContants.WF_FIELDS_KEY)) {
			// fieldsMap=PageFieldsUtil.fieldsToMap((String)variables.get("fields"));
			fields = (String) variables.get(WorkFlowContants.WF_FIELDS_KEY);
		}
		return fields;
	}

	// 当前task下的candidateGroups
	public List<IdentityLink> getIdentityLinkByTaskId(String taskId) {
		if (StringUtils.isEmpty(taskId)) {
			return null;
		}
		List<IdentityLink> IdentityLinks = taskService
				.getIdentityLinksForTask(taskId);
		return IdentityLinks;
	}

	public ActivityInstanceModel getTaskByProcessFinished(String procInstId,
			String endTaskId) {
		if (StringUtils.isEmpty(procInstId)) {
			return null;
		}
		List<HistoricTaskInstance> historicTaskInstances = historyService
				.createHistoricTaskInstanceQuery()
				.processInstanceId(procInstId).processFinished()
				.orderByHistoricTaskInstanceEndTime().desc().list();
		if (historicTaskInstances == null || historicTaskInstances.isEmpty())
			return null;
		return ActivityInstanceModel.buildAndActDef(historicTaskInstances
				.get(0), processDefinitionService.getActivity(
				historicTaskInstances.get(0).getProcessDefinitionId(),
				historicTaskInstances.get(0).getTaskDefinitionKey()));
	}
	
	public List<ActivityInstanceModel> getAllHistTaskByProcess(String procInstId) {
		if (StringUtils.isEmpty(procInstId)) {
			return null;
		}
		List<HistoricTaskInstance> historicTaskInstances = historyService
				.createHistoricTaskInstanceQuery()
				.processInstanceId(procInstId).finished()
				.orderByHistoricTaskInstanceEndTime().desc().list();
		if (historicTaskInstances == null || historicTaskInstances.isEmpty())
			return null;
		List<ActivityInstanceModel> activityInstanceModels = new ArrayList<ActivityInstanceModel>();
		for (HistoricTaskInstance task : historicTaskInstances) {
			activityInstanceModels.add(ActivityInstanceModel.buildAndActDef(
					(HistoricTaskInstance) task, null));
		}
		return activityInstanceModels;
	}

	public ActivityInstanceModel getLastTaskNotFinished(String procInstId,String endActivityId) {
		if (StringUtils.isEmpty(procInstId)) {
			return null;
		}
		List<HistoricTaskInstance> historicTaskInstances = historyService
				.createHistoricTaskInstanceQuery()
				.processInstanceId(procInstId)
				.orderByHistoricTaskInstanceStartTime().desc().list();
		if (historicTaskInstances == null || historicTaskInstances.isEmpty())
			return null;
		ActivityDefinitionModel actModel=null;
		try{
			actModel=processDefinitionService.getActivity(
					historicTaskInstances.get(0).getProcessDefinitionId(),
					historicTaskInstances.get(0).getTaskDefinitionKey());
		}catch(Exception e){
			actModel=processDefinitionService.getActivity(
					historicTaskInstances.get(0).getProcessDefinitionId(),endActivityId);
		}
		return ActivityInstanceModel.buildAndActDef(historicTaskInstances
				.get(0), actModel);
	}

	@Override
	public void claimTask(String taskId, String userId)
			throws WorkFlowException {
		if (StringUtils.isEmpty(taskId) || StringUtils.isEmpty(userId)) {
			return;
		}
		taskService.claim(taskId, userId);

	}

	@Override
	public boolean isClaimTask(String taskId) throws WorkFlowException {
		HistoricTaskInstance historicTaskInstance = historyService
				.createHistoricTaskInstanceQuery().taskId(taskId)
				.singleResult();
		if (historicTaskInstance.getClaimTime() != null) {
			return true;
		}
		return false;
	}

	@Override
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public boolean taskTransfer(String[] taskIds, String assignee,
			String transferUserId, String transferDatatype) {
		boolean result = true;
		try {
			if ("1".equals(transferDatatype)) {
				List<Task> tasks = this.taskService.createTaskQuery().active()
						.taskAssignee(assignee).list();
				for (Task task : tasks) {
					if (task == null) {
						continue;
					}
					this.taskService.setAssignee(task.getId(), transferUserId);

					// dzy签收人，待办迁移当前审核员为签收人，则签收人需更新为迁移的用户
					if(task.getOwner().equals(task.getAssignee())){
						this.taskService.setOwner(task.getId(), transferUserId);
					}
				}
			} else {
				for (String taskId : taskIds) {
					Task task = this.taskService.createTaskQuery().active()
							.taskId(taskId).singleResult();
					if (task == null) {
						continue;
					}
					this.taskService.setAssignee(taskId, transferUserId);

					// dzy签收人，待办迁移当前审核员为签收人，则签收人需更新为迁移的用户
					if(task.getOwner().equals(task.getAssignee())){
						this.taskService.setOwner(taskId, transferUserId);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			result = false;
		}
		return result;
	}

	public List<ProcessLogModel> getProcessComments(String procInstId) {
		List<ProcessLogModel> processComments = new ArrayList<ProcessLogModel>();
		if (StringUtils.isEmpty(procInstId)) {
			return processComments;
		}
		List<Comment> comments = taskService.getProcessInstanceComments(procInstId);
		Comment temp = null;

		try {
			if (comments.isEmpty())
				return processComments;
			for (int i = 0; i < comments.size(); i++) {
				Comment comment = comments.get(i);
				String taskId = comment.getTaskId();
				if (StringUtils.isEmpty(taskId)) {
					continue;
				}
				HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
						.taskId(taskId).singleResult();
				if(historicTaskInstance==null) {
					logger.error(String.format("getProcessComments historicTaskInstance出现异常,procInstId[%s],taskId[%s]", procInstId,taskId));
					historicTaskInstance=new HistoricTaskInstanceEntity();
				}
				String userName = "";
				temp = comment;
				if (StringUtils.isNotBlank(comment.getUserId())) {
					userName = userService.getUserById(comment.getUserId()).getUserName();
				}
				ProcessLogModel processComment = new ProcessLogModel();
				processComment.setComment(comment);
				processComment.setHistoricTaskInstance(historicTaskInstance);
				processComment.setSendUserId(comment.getUserId());
				processComment.setSendUserName(userName);
				processComments.add(processComment);
				try {
					if (StringUtils.isNotBlank(historicTaskInstance.getOwner())) {
						processComment
								.setOwnerName(userService.getUserById(historicTaskInstance.getOwner()).getUserName());
					}
				} catch (Exception e) {
					logger.error(String.format("获取委托人owner的userName出现异常,procInstId[%s],userId[%s]", procInstId,
							historicTaskInstance.getOwner()), e);
				}
			}
		} catch (Exception e) {
			logger.error(String.format("通过流程意见的userId获取userName出现异常,procInstId[%s],userId[%s]", procInstId,
					temp.getUserId()), e);
		}
		return processComments;
	}
	
	

	public List<ProcessLogModel> getActInstComments(String actInstId) {
		List<ProcessLogModel> processComments = new ArrayList<ProcessLogModel>();
		if(StringUtils.isEmpty(actInstId)){
			return processComments;
		}
		List<Comment> comments = taskService.getTaskComments(actInstId);
		Comment temp = null;
		try {
			if (comments.isEmpty())
				return processComments;
			for (int i = 0; i < comments.size(); i++) {
				Comment comment = comments.get(i);
				String taskId = comment.getTaskId();
				if (StringUtils.isEmpty(taskId)) {
					continue;
				}
				HistoricTaskInstance historicTaskInstance = historyService
						.createHistoricTaskInstanceQuery().taskId(taskId)
						.singleResult();
				String userName = "";
				temp = comment;
				if (StringUtils.isNotBlank(comment.getUserId())) {
					userName = userService.getUserById(comment.getUserId())
							.getUserName();
				}
				ProcessLogModel processComment = new ProcessLogModel();
				processComment.setComment(comment);
				processComment.setHistoricTaskInstance(historicTaskInstance);
				processComment.setSendUserId(comment.getUserId());
				processComment.setSendUserName(userName);
				processComments.add(processComment);
			}
		} catch (Exception e) {
			logger.error(String.format(
					"通过流程意见的userId获取userName出现异常,procInstId[%s],userId[%s]",
					actInstId, temp.getUserId()), e);
		}
		return processComments;
	}

	@Override
	public List<ActivityInstanceModel> getProcessAllTasks(String procInstId)
			throws WorkFlowException {
		if (StringUtils.isEmpty(procInstId)) {
			return null;
		}
		List<Task> tasks = taskService.createTaskQuery()
				.processInstanceId(procInstId).active().list();
		List<ActivityInstanceModel> activityInstanceModels = new ArrayList<ActivityInstanceModel>();
		for (Task task : tasks) {
			activityInstanceModels.add(ActivityInstanceModel.buildAndActDef(
					(TaskEntity) task, null));
		}
		return activityInstanceModels;

	}
	
	
	/**
	 * 找父
	 */
	@Override
	public List<ProcessInstanceModel> getAllProcessInstanceIncludeThrough(
			String procInstId) {
		List<ProcessInstanceModel> processInstanceModels = new ArrayList<ProcessInstanceModel>();
		
		return processInstanceModels;
	}
	


	@Override
	public List<ProcessInstanceModel> getThroughBizAppProcess(
			String topProcInstId) {
		List<ProcessInstanceModel> processInstanceModels = new ArrayList<ProcessInstanceModel>();
		List<HistoricProcessInstance> historicProcessInstances = this.historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(topProcInstId)
				.excludeSubprocesses(true)
				.includeProcessVariables()
				.variableValueEquals(
						WorkFlowContants.IS_THROUGH_BIZ_PROCESS_KEY,
						WorkFlowContants.IS_THROUGH_BIZ_PROCESS_YES).list();
		for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
			processInstanceModels.add(ProcessInstanceModel
					.build(historicProcessInstance));
		}
		return processInstanceModels;
	}

	@Override
	public List<ProcessInstanceModel> getAllThroughBizAppProcess(String tenantId) {
		List<ProcessInstanceModel> processInstanceModels = new ArrayList<ProcessInstanceModel>();
		List<HistoricProcessInstance> historicProcessInstances = this.historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceTenantId(tenantId)
				.includeProcessVariables()
				.variableValueEquals(
						WorkFlowContants.IS_THROUGH_BIZ_PROCESS_KEY,
						WorkFlowContants.IS_THROUGH_BIZ_PROCESS_YES).list();
		for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
			processInstanceModels.add(ProcessInstanceModel
					.build(historicProcessInstance));
		}
		return processInstanceModels;
	}

	
	/**
	 * 终止正在运行的流程实例
	 * 
	 * @author:kaka
	 * @param dkey:流程定义key,businessKey:业务id
	 */
	public void endProcessInstance(String taskId, String procDefId) {
		Task task = getTaskService().createTaskQuery().taskId(taskId).singleResult();
		if (null != task) {
			// 直接跳转到结束
			String eventActivityId = ProcessModelUtils
					.findEndTask(processModelService.getBpmnModelByProcDefId(procDefId));
			ProcessTransitionFreeService baseWfService = new ProcessTransitionFreeService(
					getProcessEngineConfiguration());
			baseWfService.commitProcess(taskId, eventActivityId, null);
		}
	} 
	


	@Override
	public List<String> getSubProcessInstanceIds(String procInstId) {
		List<String> subProcessInstanceIds = new ArrayList<String>();
		List<HistoricProcessInstance> historicProcessInstances = this.historyService.createHistoricProcessInstanceQuery().superProcessInstanceId(procInstId).list();
		for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
			subProcessInstanceIds.add(historicProcessInstance.getId());
		}
		return subProcessInstanceIds;
	}
	
	/**
	 * 找子
	 */
	@Override
	public List<ProcessInstanceModel> getSubProcessInstance(String procInstId) {
		List<ProcessInstanceModel> processInstanceModels = new ArrayList<ProcessInstanceModel>();
		StringBuffer buf=new StringBuffer();
		buf.append("select * from ACT_HI_PROCINST p where FIND_IN_SET(proc_inst_id_, getprocchildlst(#{processInstanceId}))");
		NativeHistoricProcessInstanceQuery query=this.historyService.createNativeHistoricProcessInstanceQuery();
		query.parameter("processInstanceId", procInstId);
		List<HistoricProcessInstance> historicProcessInstances = query.sql(buf.toString()).list();
		for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
			processInstanceModels.add(ProcessInstanceModel
					.build(historicProcessInstance));
		}
		return processInstanceModels;
	}
	/**
	 * 找父
	 */
	@Override
	public List<ProcessInstanceModel> getAllProcessInstance(String procInstId) {
		List<ProcessInstanceModel> processInstanceModels = new ArrayList<ProcessInstanceModel>();
		StringBuffer buf=new StringBuffer();
		buf.append("select id_, proc_inst_id_, business_key_, proc_def_id_, start_time_, end_time_, duration_, start_user_id_, start_act_id_, end_act_id_, super_process_instance_id_, delete_reason_, tenant_id_, name_, proc_title, proc_state, proc_def_name, starter_org_name, starter_org_id, starter, top_process_instance_id_," + 
				"(select assignee_user_name " + 
				"from(" + 
				"select tk.assignee_user_name,proc_inst_id_ from ACT_HI_TASKINST tk  order by tk.start_time_) tk " + 
				"where tk.proc_inst_id_=p.id_  limit 1) as START_USER_NAME from ACT_HI_PROCINST p where FIND_IN_SET(" + 
				"proc_inst_id_, getprocchildlst((select t.top_process_instance_id_  from ACT_HI_PROCINST t " + 
				"where t.proc_inst_id_=#{processInstanceId} limit 1)))");
		NativeHistoricProcessInstanceQuery query=this.historyService.createNativeHistoricProcessInstanceQuery();
		query.parameter("processInstanceId", procInstId);
		List<HistoricProcessInstance> historicProcessInstances =query.sql(buf.toString()).list();
		for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
			processInstanceModels.add(ProcessInstanceModel
					.build(historicProcessInstance));
		}
		return processInstanceModels;
	}
	/**
	 * 找顶级流程（找父）
	 */
	@Override
	public ProcessInstanceModel getTopProcessInstance(String procInstId) {
		StringBuffer buf=new StringBuffer();
		buf.append("select * from ACT_HI_PROCINST p where p.PROC_INST_ID_ =(" + 
				"select t.top_process_instance_id_  from ACT_HI_PROCINST t " + 
				"where t.proc_inst_id_=#{processInstanceId}) limit 1");
		NativeHistoricProcessInstanceQuery query=this.historyService.createNativeHistoricProcessInstanceQuery();
		query.parameter("processInstanceId", procInstId);
		HistoricProcessInstance historicProcessInstance = query.sql(buf.toString()).singleResult();
		ProcessInstanceModel processInstanceModel = ProcessInstanceModel
				.build(historicProcessInstance);
		return processInstanceModel;
	}
	
	@Override
	public List<ActivityInstanceModel> findBackAvtivity(String taskId) {
		List<ActivityInstanceModel> activityInstances = new ArrayList<ActivityInstanceModel>();
		ActivityInstanceModel curActivityInstance = this.getTask(taskId);
		ProcessInstanceModel processInstance = getProcessInstanceById(curActivityInstance
				.getProcInstId());

		ReadOnlyProcessDefinition rpd = this.getDeployedProcessDefinition(curActivityInstance
						.getProcDefId());
		// 判断是否多实例活动
		if (!rejectButActivityOperatePower.isCurActivityInstanceRejectPower(
				processInstance, curActivityInstance, rpd)) {
			return activityInstances;
		}
		String sql = "select t.* from act_hi_taskinst t,(select t.task_def_key_,max(t.end_time_) as end_time from act_hi_taskinst t  "
				+ "WHERE t.proc_inst_id_=#{processInstanceId} and task_def_key_!=#{actDefId} and end_time_ is not null and t.delete_reason_!='custom-completed' group by task_def_key_) a where t.task_def_key_=a.task_def_key_ and t.end_time_=a.end_time and t.proc_inst_id_=#{processInstanceId1} order by start_time_";
		// 获取所有当前流程实例所有已完成任务列表（不包含taskId的节点）
		NativeHistoricTaskInstanceQuery query=this.historyService.createNativeHistoricTaskInstanceQuery();
		query.parameter("processInstanceId", curActivityInstance.getProcInstId());
		query.parameter("actDefId", curActivityInstance.getActDefId());
		query.parameter("processInstanceId2", curActivityInstance.getProcInstId());
		List<HistoricTaskInstance> HistoricTaskInstances = query.sql(sql).list();
		for (HistoricTaskInstance historicTaskInstance : HistoricTaskInstances) {
			// 判断是否用户任务
			if (rejectButActivityOperatePower.isHisActivityInstanceRejectPower(
					processInstance, curActivityInstance, historicTaskInstance,
					rpd)) {
				activityInstances.add(ActivityInstanceModel.buildAndActDef(
						historicTaskInstance, null));
			}
		}
		return activityInstances;
	}


	public List<Task> getProcessTasks(String processInstanceId, String sender,
			String preTaskId) {
		if (StringUtils.isEmpty(processInstanceId)
				|| StringUtils.isEmpty(sender)) {
			return null;
		}
		NativeTaskQuery nativeTaskQuery = taskService.createNativeTaskQuery();
		StringBuffer bufSql = new StringBuffer();
		bufSql.append("select * from ACT_RU_TASK t where t.proc_inst_id_=#{processInstanceId} and t.sender=#{sender}  ");
		if (StringUtils.isNotEmpty(preTaskId)) {
			bufSql.append(" and pre_task_id=#{preTaskId} ");
		}
		bufSql.append("and t.assignee_ is not null order by t.create_time_ desc");
		nativeTaskQuery.parameter("processInstanceId", processInstanceId);
		nativeTaskQuery.parameter("sender", sender);
		if (StringUtils.isNotEmpty(preTaskId)) {
			nativeTaskQuery.parameter("preTaskId", preTaskId);
		}
		List<Task> tasks = nativeTaskQuery.sql(bufSql.toString()).list();
		return tasks;
	}

	public List<Task> getProcessTasksByTopId(String processInstanceId,
			String sender, String preTaskId) {
		if (StringUtils.isEmpty(processInstanceId)
				|| StringUtils.isEmpty(sender)) {
			return null;
		}
		NativeTaskQuery nativeTaskQuery = taskService.createNativeTaskQuery();
		StringBuffer bufSql = new StringBuffer();
		bufSql.append("select * from ACT_RU_TASK t where t.proc_inst_id_ in(select proc_inst_id_ from ACT_HI_PROCINST p where FIND_IN_SET(proc_inst_id_, getprocchildlst((select t.top_process_instance_id_  from ACT_HI_PROCINST t ");
		bufSql.append("where t.proc_inst_id_=#{processInstanceId} limit 1))))");
		bufSql.append("and t.sender=#{sender}  ");
		if (StringUtils.isNotEmpty(preTaskId)) {
			bufSql.append(" and pre_task_id=#{preTaskId} ");
		}
		bufSql.append("and t.assignee_ is not null order by t.create_time_ desc");
		nativeTaskQuery.parameter("processInstanceId", processInstanceId);
		nativeTaskQuery.parameter("sender", sender);
		if (StringUtils.isNotEmpty(preTaskId)) {
			nativeTaskQuery.parameter("preTaskId", preTaskId);
		}
		List<Task> tasks = nativeTaskQuery.sql(bufSql.toString()).list();
		return tasks;
	}

	public List<ActivityInstanceModel> getTopProcessAllTasks(
			String topProcInstId) {
		if (StringUtils.isEmpty(topProcInstId)) {
			return null;
		}
		NativeTaskQuery nativeTaskQuery = taskService.createNativeTaskQuery();
		StringBuffer bufSql = new StringBuffer();
		bufSql.append("select *from ACT_RU_TASK t where t.proc_inst_id_ in(select p.proc_inst_id_ from ACT_HI_PROCINST p where p.top_process_instance_id_=#{topProcessInstanceId}) ");
		nativeTaskQuery.parameter("topProcessInstanceId", topProcInstId);
		List<Task> tasks = nativeTaskQuery.sql(bufSql.toString()).list();
		List<ActivityInstanceModel> activityInstanceModels = new ArrayList<ActivityInstanceModel>();
		for (Task task : tasks) {
			activityInstanceModels.add(ActivityInstanceModel.buildAndActDef(
					(TaskEntity) task, null));
		}
		return activityInstanceModels;
	}
}
