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

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

import org.activiti.bpmn.constants.BpmnXMLConstants;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import com.blueland.bpm.common.util.StringUtils;
import com.blueland.bpm.engine.core.model.ActivityResourceModel;
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.service.ProcessTransitionFreeService;
import com.blueland.bpm.engine.util.PageFieldsUtil;
import com.blueland.bpm.engine.util.ProcessDefinitionUtils;
import com.blueland.bpm.engine.util.WorkFlowContants;
import com.blueland.bpm.engine.util.WorkFlowException;
/**
 * 新建流程执行类
 * @version:  1.0
 * @author lw 
 */
@Service(WorkFlowContants.ACTION_TYPE_LAUCH_PROCESS)
public class LauchProcessExecutor extends AbstractProcessExecutor implements ProcessExecutor{
	@Override
	public ProcessInstanceModel execute(ProcessInputModel processInputModel)
			throws WorkFlowException {

		validateProcessInputModel(processInputModel);
		ProcessDefinition processDefinition = getProcessDefinition(processInputModel.getWf_procDefId());
		additionalProcessInputModel(processInputModel, processDefinition);
		Map<String, Object> workflowMap = new HashMap<String, Object>();
		// 设置页面fields
		processInputModel.setWf_fields(PageFieldsUtil
				.fieldsToXml(processInputModel.getFields()));
		workflowMap.putAll(processInputModel.getWf_variables());
		workflowMap.put(WorkFlowContants.WF_FIELDS_KEY,processInputModel.getWf_fields());
		workflowMap.put(WorkFlowContants.WF_PROCESS_INPUT_VARIABLE_KEY,
				processInputModel);
		String receiver = processInputModel.getWf_receiver();
		String sender = processInputModel.getWf_sender();
		
		// 设置流程发起人
		identityService
				.setAuthenticatedUserId(processInputModel.getWf_sender());
		// 起草流程特殊处理
		processInputModel.setWf_receiver(sender);

		// 启动流程
		ProcessInstance processInstance = runtimeService
				.startProcessInstanceById(processInputModel.getWf_procDefId(),
						processInputModel.getWf_businessKey(), workflowMap);
		// 根据sender获取起草环节的任务
		Task task = this.findTaskByAssignee(processInstance.getId(), sender);
		// 起草有点特殊,有2条数据
		processInputModel.setWf_receiver(receiver);
		processInputModel.setWf_actionType(WorkFlowContants.ACTION_TYPE_EXECUTE_ACTIVITY);

		// 下一步环节为空时,根据规则自动查询出下一步环节
		if (StringUtils.isEmpty(processInputModel.getWf_nextActDefId())) {
			autoSetNextActDefId(processInputModel);
			processInputModel.setWf_webAutoQueryNextActFlag(true);
		}
		if (StringUtils.isNotBlank(processInputModel.getWf_receiver())) {
			// 处理下一环节为多实例
			if (ProcessDefinitionUtils.isMultiInstance(processInputModel,
					repositoryService)) {
				List<String> receiverList = convertReceivers(processInputModel
						.getWf_receiver());
				workflowMap.put(WorkFlowContants.ELEMENT_ASSIGNEE_LIST,
						receiverList);
			}
		} else if (ProcessDefinitionUtils.isUserTask(processInputModel)
				|| BpmnXMLConstants.ELEMENT_TASK_SERVICE
						.equals(processInputModel.getWf_nextActDefType())) {
			// 下一步人员为空,自动路由到环节绑定的资源中的最前一个人
			List<ActivityResourceModel> users = processDefinitionService
					.getActivityUserTree("",
							processInputModel.getWf_procDefId(), null,
							processInputModel.getWf_curActDefId(),
							processInputModel.getWf_nextActDefId(),
							processInputModel.getWf_sendUserId(),
							processInputModel.getWf_sendUserOrgId(), null,
							workflowMap);
			processInputModel.setWf_receiver(getTreeNodeOneUser(users));
			processInputModel.setWf_webAutoQueryNextUserFlag(true);
		}

		// 完成当前任务并触发下一步任务
		ProcessTransitionFreeService baseWfService = new ProcessTransitionFreeService(
				processEngineConfiguration);

		ProcessInstanceModel processInstanceModel = null;

		try {
			// 完成任务后做一些业务逻辑
			if (StringUtils.isNotBlank(processInputModel.getWf_curComment())) {
				taskService.addComment(task.getId(),
						task.getProcessInstanceId(),
						processInputModel.getWf_curComment(),
						processInputModel.getWf_commentDisplayArea());
			}
			baseWfService.commitProcess(task.getId(),
						processInputModel.getWf_nextActDefId(), workflowMap);
			processInstanceModel = processInstanceModellBuilder
					.builderProcessInfo(processInputModel, processDefinition,
							processInstance, task);
		} catch (Exception e) {
			throw new WorkFlowException(ExceptionErrorCode.B2050,String.format(
					"流程发起失败,task[%s],processInputModel[%s]", task,
					processInputModel), e);
		}
		// 设置返回参数
		return processInstanceModel;

	}

}
