package com.blueland.bpm.engine.core.model;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

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.util.WorkFlowContants;
/**
 * 流程实例构造类
 * 
 * @version: 1.0
 * @author lw
 */
@Service
public class ProcessInstanceModellBuilder extends AbstractServiceHelper {
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Resource(name="processInstanceServiceImpl")
	ProcessInstanceService processInstanceService;
	@Resource(name="processDefinitionServiceImpl")
	ProcessDefinitionService processDefinitionService;
	
	public ProcessInstanceModel builderProcessInfoNoNextTask(
			ProcessInputModel processInputModel,
			ProcessDefinition processDefinition,
			ProcessInstance processInstance, Task tempCurrentTask) {
		ProcessInstanceModel processInfo = null;
		ExecutionEntity executionEntity = (org.activiti.engine.impl.persistence.entity.ExecutionEntity) processInstance;
		if (WorkFlowContants.ACTION_TYPE_LAUCH_PROCESS.equals(processInputModel
				.getWf_actionType())
				|| WorkFlowContants.ACTION_TYPE_LAUCH_SAVE_PROCESS
						.equals(processInputModel.getWf_actionType())) {
			processInfo = ProcessInstanceModel.buildAndProcDef(executionEntity,
					ProcessDefinitionModel.build(processDefinition));
		} else {
			HistoricProcessInstance historicProcessInstance = this.historyService
					.createHistoricProcessInstanceQuery()
					.processInstanceId(processInstance.getId()).singleResult();
			if(historicProcessInstance==null){
				processInfo = ProcessInstanceModel.buildAndProcDef(executionEntity,
						ProcessDefinitionModel.build(processDefinition));
			}else{
				processInfo = ProcessInstanceModel.buildAndProcDef(
						historicProcessInstance,
						ProcessDefinitionModel.build(processDefinition));
			}
		}
		processInfo.processVariables = processInstance.getProcessVariables();
		processInfo.processInputModel=processInputModel;
		TaskEntity currentTask = (TaskEntity) tempCurrentTask;
		if(currentTask==null||currentTask.getId()==null){
			processInfo.actionType = processInputModel.getWf_actionType();
			return processInfo;
		}
		processInfo.actionType = currentTask.getActionType();
		ActivityInstanceModel curtActivityInfo = builderCurrentActivityInfo(
				executionEntity, currentTask);
		processInfo.currentActivity = curtActivityInfo;
		return processInfo;
	}
	
	
	public ProcessInstanceModel builderProcessInfo(
			ProcessInputModel processInputModel,
			ProcessDefinition processDefinition,
			ProcessInstance processInstance, Task tempCurrentTask) {
		ProcessInstanceModel processInfo = builderProcessInfoNoNextTask(
				processInputModel, processDefinition, processInstance,
				tempCurrentTask);
		if (!(WorkFlowContants.ACTION_TYPE_CANCEL_PROCESS
				.equals(processInputModel.getWf_actionType())
				|| WorkFlowContants.ACTION_TYPE_SAVE_ACTIVITY
						.equals(processInputModel.getWf_actionType()))) {
			if(processInfo.getCurrentActivity()!=null) {
			List<ActivityInstanceModel> nextActivityInfo = builderNextActivityInfo(
					processInfo.getProcInstId(), processInfo
							.getCurrentActivity().getReceiver());
			processInfo.nextActivity = nextActivityInfo;
			}
		}
		if (WorkFlowContants.ACTION_TYPE_LAUCH_PROCESS.equals(processInputModel
				.getWf_actionType())
				|| WorkFlowContants.ACTION_TYPE_EXECUTE_ACTIVITY
						.equals(processInputModel.getWf_actionType())) {
			try {
				processInfo.subProcInstIds = processInstanceService
						.getSubProcessInstanceIds(processInfo.getProcInstId());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return processInfo;
	}
	
	public ProcessInstanceModel builderProcess(
			ProcessInputModel processInputModel,
			ProcessDefinition processDefinition,
			ProcessInstance processInstance, Task tempCurrentTask) {
		ProcessInstanceModel processInfo = builderProcessInfoNoNextTask(
				processInputModel, processDefinition, processInstance,
				tempCurrentTask);
		if (!(WorkFlowContants.ACTION_TYPE_CANCEL_PROCESS
				.equals(processInputModel.getWf_actionType())
				|| WorkFlowContants.ACTION_TYPE_SAVE_ACTIVITY
						.equals(processInputModel.getWf_actionType()))) {
		  List<ActivityInstanceModel> nextActivityInfo = builderNextActivityInfo(
					processInfo.getProcInstId(), processInfo
							.getCurrentActivity().getReceiver());
			processInfo.nextActivity = nextActivityInfo;
		}
		if (WorkFlowContants.ACTION_TYPE_LAUCH_PROCESS.equals(processInputModel
				.getWf_actionType())
				|| WorkFlowContants.ACTION_TYPE_EXECUTE_ACTIVITY
						.equals(processInputModel.getWf_actionType())) {
			try {
				processInfo.subProcInstIds = processInstanceService
						.getSubProcessInstanceIds(processInfo.getProcInstId());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return processInfo;
	}
	
	
	public  ActivityInstanceModel builderCurrentActivityInfo(ProcessInstance processInstance,Task task){
		TaskEntity currentTask=(TaskEntity) task;
		ActivityDefinitionModel defModel=null;
		try{
			 defModel=processDefinitionService.getActivity(currentTask.getProcessDefinitionId(), currentTask.getTaskDefinitionKey());
		}catch(Exception e){
			//e.printStackTrace();
			defModel=new ActivityDefinitionModel();
		}
		ActivityInstanceModel activityInfo=ActivityInstanceModel.buildAndActDef(currentTask, defModel);
		return activityInfo;
	}

	public List<ActivityInstanceModel> builderNextActivityInfo(String topProcessInstanceId,String assignee) {
		List<ActivityInstanceModel> activityInfos = new ArrayList<ActivityInstanceModel>();
		List<Task> nextTasks = null;
		try{nextTasks=processInstanceService.getProcessTasks(topProcessInstanceId, assignee,"");
		}catch(Exception e){
			e.printStackTrace();
		}
		if (nextTasks == null||nextTasks.isEmpty())
			return activityInfos;
		for (Task tempNextTask : nextTasks) {
			TaskEntity nextTask = (TaskEntity) tempNextTask;
			ActivityInstanceModel activityInfo=ActivityInstanceModel.buildAndActDef(nextTask, processDefinitionService.getActivity(nextTask.getProcessDefinitionId(), nextTask.getTaskDefinitionKey()));
			activityInfos.add(activityInfo);
		}
		return activityInfos;
	}
}
