package com.blueland.ebpm.rest;

import com.blueland.bpm.common.page.impl.ListPage;
import com.blueland.bpm.common.util.SysConfig;
import com.blueland.bpm.engine.core.model.*;
import com.blueland.bpm.engine.core.service.ProcessDefinitionService;
import com.blueland.bpm.engine.core.service.ProcessExecuteServiceFacde;
import com.blueland.bpm.engine.core.service.ProcessInstanceService;
import com.blueland.bpm.engine.core.service.ProcessTraceService;
import com.blueland.bpm.engine.util.WorkFlowContants;
import com.blueland.ebpm.bean.BeansBuilder;
import com.blueland.ebpm.bean.ProcessInstanceBean;
import com.blueland.ebpm.exception.RestException;
import com.blueland.ebpm.util.RestUtils;
import com.blueland.unitework.model.UniteworkTask;
import com.blueland.unitework.service.UniteworkService;
import com.google.common.collect.Maps;
import org.activiti.engine.IdentityService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@RestController
@RequestMapping(value="/processinstance")
public class ProcessInstanceController {

	@Autowired
	private ProcessInstanceService processInstanceService;
	
	@Autowired
	private ProcessExecuteServiceFacde processExecuteService;
	
	@Autowired
	private ProcessTraceService processTraceService;
	
	@Autowired
	protected IdentityService identityService;
	
	@Autowired
	protected TaskService taskService;
	
	@Autowired
	private ProcessDefinitionService processDefinitionService;
	
	@Autowired
	private UniteworkService uniteworkService;
	
	@Autowired
	private BeansBuilder beansBuilder;
	
	@RequestMapping(value = "/{procInstId}/id", produces="application/json; charset=UTF-8")
	public ProcessInstanceBean getProcInstById(@PathVariable String procInstId) {
		ProcessInstanceModel model = processInstanceService.getProcessInstanceById(procInstId);	
		if(model == null) {
			throw new RestException(ExceptionErrorCode.B2051.name(), "process instance not found, id=" + procInstId);
		}
		return beansBuilder.build(model);
	}
	
	@RequestMapping(value="/{bussisnesKey}/bizkey", produces="application/json; charset=UTF-8")
	public ProcessInstanceBean getProcInstByBizkey(@PathVariable String bussisnesKey) {
		ProcessInstanceModel model = processInstanceService.getProcessInstanceByBizKey(bussisnesKey);
		return beansBuilder.build(model);
	}
	
	@RequestMapping(value="/{bussisnesKey}/bizkeys", produces="application/json; charset=UTF-8")
	public List<ProcessInstanceBean> getProcesInstByBizkey(@PathVariable String bussisnesKey) {
		List<ProcessInstanceModel> list = processInstanceService.getProcessInstancesByBizKey(bussisnesKey);
		return beansBuilder.buildProcInstList(list);
	}	
	
	@RequestMapping(value="/{procInstId}/histasklog", produces="application/json; charset=UTF-8")
	public Map<String,Object> getHisTaskLog(@PathVariable String procInstId){
		Map<String, Object> tmpResult = processTraceService.getHisTaskLog(procInstId);
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("procInst", beansBuilder.build((HistoricProcessInstanceEntity)tmpResult.get("curProcessInstance")));
		result.put("procLogs", beansBuilder.buildProcessLogList((List<ProcessLogModel>)tmpResult.get("processDetailLogs")));
		return result;
	}
	
	
	@RequestMapping(value="/{topProcInstId}/histaskcomentlog", produces="application/json; charset=UTF-8")
	public Map<String,Object> getHisTaskComentLog(@PathVariable String topProcInstId){
		Map<String, Object> tmpResult = processTraceService.getHisTaskComments(topProcInstId);
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("procInst", beansBuilder.build((HistoricProcessInstanceEntity)tmpResult.get("curProcessInstance")));
		result.put("procLogs", beansBuilder.buildProcessLogList((List<ProcessLogModel>)tmpResult.get("processDetailLogs")));
		return result;
	}
	
	//@RequestMapping(value="/{procInstId}/histasklogurl", produces="text/plain; charset=UTF-8")
	@RequestMapping(value="/{procInstId}/histasklogurl", produces="application/json; charset=UTF-8")
	public Map<String,String> getProcLogUrl(@PathVariable String procInstId) {
		String url = SysConfig.getValue("MANAGE_URL") + "/workflow/trace/traceProcess.do?processInstanceId=" + procInstId;
		Map<String,String> result = new HashMap<String,String>();
		result.put("url", url);
		return result;
	}
	
	@RequestMapping(value="/{procInstId}/dataobject", produces="application/json; charset=UTF-8")
	public BusinessDataObject getProcDataObject(@PathVariable String procInstId) {
		return processInstanceService.getBusinessDataObject(procInstId);
	}
	
//	@RequestMapping(value="/runtime/processinstance/getactdataobject", produces="application/json; charset=UTF-8")
//	public BusinessDataObject getActDataObject(@RequestParam String actInstId) {
//		return (BusinessDataObject) processInstanceService.getTaskVariables(actInstId).get("wf_businessDataObject");
//	}	
	
	@RequestMapping(value="/createprocinst", method = RequestMethod.POST, produces="application/json; charset=UTF-8")
	public ProcessInstanceBean createProcinst(@RequestBody ProcessInputModel model){
		Map<String, Object> result = new HashMap<String, Object>();
		
		if(RestUtils.isEmpty(model.getWf_sendUserId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserId is null");
		}		
		/*if(RestUtils.isEmpty(model.getWf_sendUserOrgId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserOrgId is null");
		}*/
		if(RestUtils.isEmpty(model.getWf_procTitle())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_procTitle is null");
		}
//		if(StringUtils.isEmpty(model.getWf_businessKey())) {
//			result.put("errorMsg","业务标识字段（wf_businessKey)不能为空");
//			return result;
//		}

		String procDefId = model.getWf_procDefId();
		String procDefKey = model.getWf_procDefKey();
		if(RestUtils.isEmpty(procDefId) && RestUtils.isEmpty(procDefKey)) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_procDefId and wf_procDefKey is null");
		}
		ProcessDefinitionModel procDefModel = null;
		if(RestUtils.isEmpty(procDefKey))
			procDefModel = processDefinitionService.getProcessDef(procDefId);
		else
			procDefModel = processDefinitionService.getProcessDefBykey(procDefKey);
		if(procDefModel == null) {
			throw new RestException(ExceptionErrorCode.B2002.name(), "process definition not found, id=" + procDefId + ",key=" + procDefKey);
		}
		else {
			model.setWf_procDefId(procDefModel.getProcDefId());
			model.setWf_procDefKey(procDefModel.getProcDefKey());
			model.setWf_procDefName(procDefModel.getProcDefName());
			model.setWf_appId(procDefModel.getTenantId());
		}
		
		if(!RestUtils.isEmpty(model.getWf_curActInstId())) {
			ActivityInstanceModel curActInstModel = this.processInstanceService.getTask(model.getWf_curActInstId());
			model.setWf_procInstId(curActInstModel.getProcInstId());
		}
		model.setWf_actionType(WorkFlowContants.ACTION_TYPE_SAVE_ACTIVITY);
		result = processExecuteService.nextExecute(model);
		if(result.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)result.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)result.get("executeErrorCode")).name() , (String)result.get("executeErrorMsg"));
		}
	}
	
	/*
	@RequestMapping(value="/lunchprocinst", method = RequestMethod.POST,produces="application/json; charset=UTF-8")
	public ProcessInstanceBean lunchProceInst(@RequestBody ProcessInputModel model){		
		Map<String, Object> result = new HashMap<String, Object>();
		
		if(StringUtils.isEmpty(model.getWf_sendUserId())) {
			throw new IllegalArgumentException("wf_sendUserId is null");
		}		
		if(StringUtils.isEmpty(model.getWf_sendUserOrgId())) {
			throw new IllegalArgumentException("wf_sendUserOrgId is null");
		}
		
		if(StringUtils.isEmpty(model.getWf_procTitle())) {
			throw new IllegalArgumentException("wf_procTitle is null");
		}
//		if(StringUtils.isEmpty(model.getWf_businessKey())) {
//			result.put("errorMsg","业务标识字段（wf_businessKey)不能为空");
//			return result;
//		}

		String procDefId = model.getWf_procDefId();
		String procDefKey = model.getWf_procDefKey();
		if(StringUtils.isEmpty(procDefId) && StringUtils.isEmpty(procDefKey)) {
			throw new IllegalArgumentException("wf_procDefId and wf_procDefKey is null");
		}
		ProcessDefinitionModel procDefModel = null;
		if(StringUtils.isEmpty(procDefKey))
			procDefModel = processDefinitionService.getProcessDef(procDefId);
		else
			procDefModel = processDefinitionService.getProcessDefBykey(procDefKey);
		if(procDefModel == null) {
			throw new RestException("process definition not found");
		}
		else {
			model.setWf_procDefId(procDefModel.getProcDefId());
			model.setWf_procDefKey(procDefModel.getProcDefKey());
			model.setWf_procDefName(procDefModel.getProcDefName());
			model.setWf_appId(procDefModel.getTenantId());
		}
		
		if(StringUtils.isEmpty(model.getWf_curActDefId())) {
			throw new IllegalArgumentException("wf_curActDefId is null");
		}
		
		ActivityDefinitionModel curActModel = processDefinitionService.getActivity(procDefModel.getProcDefId(), model.getWf_curActDefId());
		if(curActModel == null) {
			throw new RestException("current activity definition not found");
		}else {
			model.setWf_curActDefName(curActModel.getActDefName());
			model.setWf_curActDefType(curActModel.getActType());
		}
		
//		if(StringUtils.isEmpty(model.getWf_nextActDefId())) {
//			throw new IllegalArgumentException("wf_nextActDefid is null");
//		}
		
		if(!StringUtils.isEmpty(model.getWf_nextActDefId())) {
			ActivityDefinitionModel destActModel = processDefinitionService.getActivity(procDefModel.getProcDefId(), model.getWf_nextActDefId());
			model.setWf_nextActDefName(destActModel.getActDefName());
			model.setWf_nextActDefType(destActModel.getActType());
		}
		
//		if(StringUtils.isEmpty(model.getWf_receiver())) {
//			result.put("errMsg", "接收人字段(wf_receiver)不能为空");
//			return result;
//		}

		model.setWf_actionType(WorkFlowContants.ACTION_TYPE_LAUCH_PROCESS);
		result = processExecuteService.nextExecute(model);
		if(result.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)result.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException("lunch process instance error");
		}
	}	*/
	

	@RequestMapping(value="/nextexecute",method = RequestMethod.POST,produces="application/json; charset=UTF-8")
	public ProcessInstanceBean nextExcute(@RequestBody ProcessInputModel model){
		Map<String, Object> result = new HashMap<String, Object>();

		if(RestUtils.isEmpty(model.getWf_sendUserId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserId is null");
		}		
		/*if(RestUtils.isEmpty(model.getWf_sendUserOrgId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserOrgId is null");
		}*/
		
		if(RestUtils.isEmpty(model.getWf_procTitle())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_procTitle is null");
		}	
		
		String procDefId = model.getWf_procDefId();
		String procDefKey = model.getWf_procDefKey();

		if(RestUtils.isEmpty(model.getWf_curActInstId())) {  //新建？
			model.setWf_actionType(WorkFlowContants.ACTION_TYPE_LAUCH_PROCESS);
			if(RestUtils.isEmpty(procDefId) && RestUtils.isEmpty(procDefKey)) {
				throw new RestException(ExceptionErrorCode.B2001.name(), "wf_procDefId and wf_procDefKey is null");
			}
			ProcessDefinitionModel procDefModel = null;
			if(RestUtils.isEmpty(procDefId))
				procDefModel = processDefinitionService.getProcessDefBykey(procDefKey);
			else
				procDefModel = processDefinitionService.getProcessDef(procDefId);
			if(procDefModel == null) {
				throw new RestException(ExceptionErrorCode.B2001.name(), "process definition not found, id=" + procDefId + ", key=" + procDefKey);
			}
			else {
				model.setWf_procDefId(procDefModel.getProcDefId());
				model.setWf_procDefKey(procDefModel.getProcDefKey());
				if(StringUtils.isEmpty(model.getWf_curActDefId())) {
					model.setWf_curActDefId(processDefinitionService.getStartActivity(procDefModel.getProcDefId()).getActDefId());
				}
				model.setWf_procDefKey(procDefModel.getProcDefKey());
				model.setWf_procDefName(procDefModel.getProcDefName());
				model.setWf_appId(procDefModel.getTenantId());
			}
		}else {
			model.setWf_actionType(WorkFlowContants.ACTION_TYPE_EXECUTE_ACTIVITY);
			ActivityInstanceModel curActInst = processInstanceService.getTask(model.getWf_curActInstId());
			if(curActInst == null) 
				throw new RestException(ExceptionErrorCode.B2052.name() ,"current activity instance not found, id=" + model.getWf_curActInstId());
			
			UniteworkTask uniteworkTask = uniteworkService.getByActInstId(model.getWf_curActInstId());
			if(uniteworkTask == null) {
				throw new RestException(ExceptionErrorCode.B2052.name(), "unitework task not found, curActIndtId=" + model.getWf_curActInstId());
			}
			if(StringUtils.isNotEmpty(model.getWf_batchId())) {
				if(model.getWf_batchId().equals("no")) {//不使用批次逻辑
					model.setWf_batchId(null);
				}else{//批次逻辑不同流程不同环节可以更改
					
				}
			}else {//批次逻辑一个流程实例沿用一套，沿用流程批次逻辑
				model.setWf_batchId(uniteworkTask.getBatchId());
			}
			procDefId = curActInst.getProcDefId();
			model.setWf_procInstId(curActInst.getProcInstId());
			model.setWf_procDefId(curActInst.getProcDefId());
			model.setWf_procDefKey(uniteworkTask.getProcDefKey());
			model.setWf_procDefName(curActInst.getProcDefName());
			model.setWf_appId(curActInst.getTenantId());	
			model.setWf_curActDefId(curActInst.getActDefId());
		}

		if(RestUtils.isEmpty(model.getWf_curActDefId()))
			throw new IllegalArgumentException("curActDefId is null");
		ActivityDefinitionModel curActModel = processDefinitionService.getActivity(model.getWf_procDefId(), model.getWf_curActDefId());
		if(curActModel == null) {
			throw new RestException(ExceptionErrorCode.B2003.name(), "current activity definition not found, procid=" + procDefId + ",actid=" + model.getWf_curActDefId());
		}else {
			model.setWf_curActDefName(curActModel.getActDefName());
			model.setWf_curActDefType(curActModel.getActType());
		}
	
//		if(StringUtils.isEmpty(model.getWf_nextActDefId())) {
//			result.put("errorMsg", "下一活动Id字段(wf_nextActDefId)不能为空");
//			return result;
//		}
	
		if(!RestUtils.isEmpty(model.getWf_nextActDefId())) {
			ActivityDefinitionModel destActModel = processDefinitionService.getActivity(model.getWf_procDefId(), model.getWf_nextActDefId());
			model.setWf_nextActDefName(destActModel.getActDefName());
			model.setWf_nextActDefType(destActModel.getActType());
		}
//		if(destActModel == null) {
//			result.put("errMsg", "没有找到目标活动");
//			return result;
//		}else {
//			model.setWf_nextActDefName(destActModel.getActDefName());
//			model.setWf_nextActDefType(destActModel.getActType());
//		}
		
//		if(StringUtils.isEmpty(model.getWf_receiver())) {
//			result.put("errMsg", "接收人字段(wf_receiver)不能为空");
//			return result;
//		}

		result = processExecuteService.nextExecute(model);
		if(result.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)result.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)result.get("executeErrorCode")).name() , (String)result.get("executeErrorMsg"));
		}
	}
	
	public static void main(String[] args) {
		Random ran1 = new Random(10);
		System.out.println(ran1.nextInt()+"");
	}
	
	
	@RequestMapping(value = "/nextExcuteBatch", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
	public Map<String, Object> nextExcuteBatch(@RequestBody final List<ProcessInputModel> models) {
		System.out.println("数据大小：" + models.size());
		long start = System.currentTimeMillis();
		ListPage page = new ListPage(models, 1, 10);
		int totalPage = page.getLastPageNumber();

		Map<String, Object> results = new HashMap<String, Object>();
		ExecutorService execservice = Executors.newFixedThreadPool(totalPage);
		for (int i = 1; i <= totalPage; i++) {
			final List result = page.getResult();
			execservice.execute(new Runnable() {
				@Override
				public void run() {
					int j = 0;
					for (ProcessInputModel processInputModel : models) {
						try {
							System.out.println("执行j:" + j);
							nextExcute(processInputModel);
						} catch (Exception e) {
							e.printStackTrace();
						}
						j++;
					}
				}
			});
			page = new ListPage(models, i + 1, 10);
			System.out.println("执行i:" + i);
		}

		execservice.shutdown();
		while (true) {
			if (execservice.isTerminated()) {
				System.out.println("所有的子线程都结束了！");
				break;
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		/*
		 * List<ProcessInstanceBean> successResult=new ArrayList<ProcessInstanceBean>();
		 * List<ProcessInputModel> errors=new ArrayList<ProcessInputModel>(); int i=1;
		 * for (ProcessInputModel processInputModel : models) { try {
		 * ProcessInstanceBean result=this.nextExcute(processInputModel);
		 * successResult.add(result); }catch(Exception e) {
		 * errors.add(processInputModel); } System.out.println("处理完："+i); i++; }
		 */
		results.put("sucess", "");
		results.put("errors", "");
		long end = System.currentTimeMillis();

		System.out.println("数据大小：" + models.size() + ",耗时：" + (end - start));
		return results;

	}
	
	@RequestMapping(value="/cancelprocinst", method = RequestMethod.POST,produces="application/json; charset=UTF-8")
	public ProcessInstanceBean cancelProcInst(@RequestBody ProcessInputModel model) {
		String procInstId = model.getWf_procInstId();
		if(RestUtils.isEmpty(procInstId)) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "procInstId is null");
		}
	
		ProcessInstance processInstance=processInstanceService.getRuntimeService().createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
		if(processInstance == null) {
			throw new RestException(ExceptionErrorCode.B2051.name(), "process instance not found, id=" + procInstId);
		}
		List<Task> tasks=processInstanceService.getTaskService().createTaskQuery().processInstanceId(processInstance.getId()).active().orderByTaskCreateTime().desc().list();
		if(tasks == null || tasks.isEmpty()) {
			throw new RestException(ExceptionErrorCode.B2052.name(), "no task found");
		}
		Task task = tasks.get(0);
		ProcessInputModel processInputModel =(ProcessInputModel) processInstanceService.getTaskVariables(task.getId()).get(WorkFlowContants.WF_PROCESS_INPUT_VARIABLE_KEY);
		processInputModel.setWf_procTitle(task.getProcTitle());
		processInputModel.setWf_actionType(WorkFlowContants.ACTION_TYPE_CANCEL_PROCESS);
		processInputModel.setWf_curActInstId(task.getId());
		processInputModel.setWf_procDefId(task.getProcessDefinitionId());
		processInputModel.setWf_procInstId(task.getProcessInstanceId());
		processInputModel.setWf_appId(task.getTenantId()); //?
		processInputModel.setWf_curComment(model.getWf_curComment());
		Map<String, Object> resultMap = processExecuteService.nextExecute( processInputModel);
		if(resultMap.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)resultMap.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)resultMap.get("executeErrorCode")).name() , (String)resultMap.get("executeErrorMsg"));
		}
	}
	
	@RequestMapping(value="/backtostart", method = RequestMethod.POST,produces="application/json; charset=UTF-8")
	public ProcessInstanceBean backToStart(@RequestBody ProcessInputModel model){
		ActivityInstanceModel activityInstanceModel = processInstanceService.getTask(model.getWf_curActInstId());
		if (activityInstanceModel == null) {
			throw new RestException(ExceptionErrorCode.B2052.name(), "activity instance not found, id=" + model.getWf_curActInstId());
		}
		
		if(RestUtils.isEmpty(model.getWf_sendUserId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserId is null");
		}		
		/*if(RestUtils.isEmpty(model.getWf_sendUserOrgId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserOrgId is null");
		}*/
		//ProcessInputModel processInputModel =(ProcessInputModel) processInstanceService.getTaskVariables(activityInstanceModel.getActInstId()).get(WorkFlowContants.WF_PROCESS_INPUT_VARIABLE_KEY);
		
		UniteworkTask uniteworkTask = uniteworkService.getByActInstId(model.getWf_curActInstId());
		if(uniteworkTask == null)
			throw new RestException(ExceptionErrorCode.B2052.name(), "unitework task not found, curActIndtId=" + model.getWf_curActInstId());
		if(StringUtils.isNotEmpty(model.getWf_batchId())) {
			if(model.getWf_batchId().equals("no")) {//不使用批次逻辑
				model.setWf_batchId(null);
			}else{//批次逻辑不同流程不同环节可以更改
				
			}
		}else {//批次逻辑一个流程实例沿用一套，沿用流程批次逻辑
			model.setWf_batchId(uniteworkTask.getBatchId());
		}
//		processInputModel.setWf_sendUserId(model.getWf_sendUserId());
//		processInputModel.setWf_sendUserOrgId(model.getWf_sendUserOrgId());
//		processInputModel.setWf_businessDataObject(model.getWf_businessDataObject());
//		processInputModel.setWf_curComment(model.getWf_curComment());
//		processInputModel.setWf_uniteworkUrl(model.getWf_uniteworkUrl());
		
		model.setWf_actionType(WorkFlowContants.ACTION_TYPE_CALLBACK_START_ACTIVITY);
		model.setWf_curActDefId(activityInstanceModel.getActivityDefinition().getActDefId());
		model.setWf_curActDefName(activityInstanceModel.getActivityDefinition().getActDefName());
		model.setWf_curActDefType(activityInstanceModel.getActivityDefinition().getActType());
		model.setWf_procDefId(activityInstanceModel.getProcDefId());
		model.setWf_procDefKey(uniteworkTask.getProcDefKey());
		model.setWf_procDefName(uniteworkTask.getProcDefName());
		model.setWf_appId(activityInstanceModel.getTenantId());
		model.setWf_procInstId(activityInstanceModel.getProcInstId());
		
		Map<String, Object> resultMap = processExecuteService.nextExecute(model);
		if(resultMap.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)resultMap.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)resultMap.get("executeErrorCode")).name() , (String)resultMap.get("executeErrorMsg"));
		}
	}
	
	@RequestMapping(value="/backtoprev", method = RequestMethod.POST,produces="application/json; charset=UTF-8")
	public ProcessInstanceBean backToPrev(@RequestBody ProcessInputModel model){
		if(RestUtils.isEmpty(model.getWf_sendUserId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserId is null");
		}		
		/*if(RestUtils.isEmpty(model.getWf_sendUserOrgId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserOrgId is null");
		}*/
		String curActInstId = model.getWf_curActInstId();
		if(RestUtils.isEmpty(curActInstId)) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_curActInstId is null");
		}
		ActivityInstanceModel activityInstanceModel=processInstanceService.getTask(curActInstId);
		if(activityInstanceModel == null) {
			throw new RestException(ExceptionErrorCode.B2052.name(), "activity instance not found, id=" + curActInstId);
		}
		//HistoricVariableInstance hisVarInst=processInstanceService.getHistoryService().createHistoricVariableInstanceQuery().processInstanceId(activityInstanceModel.getProcInstId()).variableName(WorkFlowContants.WF_PROCESS_INPUT_VARIABLE_KEY).orderByLastUpdateTime().desc().singleResult();
		//ProcessInputModel processInputModel=(ProcessInputModel)hisVarInst.getValue();
		//ProcessInputModel processInputModel =(ProcessInputModel) processInstanceService.getTaskVariables(activityInstanceModel.getActInstId()).get(WorkFlowContants.WF_PROCESS_INPUT_VARIABLE_KEY);
		UniteworkTask uniteworkTask = uniteworkService.getByActInstId(curActInstId);
		if(uniteworkTask == null)
			throw new RestException(ExceptionErrorCode.B2052.name(), "unitework task not found, curActIndtId=" + curActInstId);
		if(StringUtils.isNotEmpty(model.getWf_batchId())) {
			if(model.getWf_batchId().equals("no")) {//不使用批次逻辑
				model.setWf_batchId(null);
			}else{//批次逻辑不同流程不同环节可以更改
				
			}
		}else {//批次逻辑一个流程实例沿用一套，沿用流程批次逻辑
			model.setWf_batchId(uniteworkTask.getBatchId());
		}
//		processInputModel.setWf_sendUserId(model.getWf_sendUserId());
//		processInputModel.setWf_sendUserOrgId(model.getWf_sendUserOrgId());
//		processInputModel.setWf_businessDataObject(model.getWf_businessDataObject());
//		processInputModel.setWf_curComment(model.getWf_curComment());
//		processInputModel.setWf_uniteworkUrl(model.getWf_uniteworkUrl());
//		processInputModel.setWf_procTitle(model.getWf_procTitle());
		
		model.setWf_actionType(WorkFlowContants.ACTION_TYPE_CALLBACK_PREV_ACTIVITY);
		
		
		model.setWf_curActDefId(activityInstanceModel.getActivityDefinition().getActDefId());
		model.setWf_curActDefName(activityInstanceModel.getActivityDefinition().getActDefName());
		model.setWf_curActDefType(activityInstanceModel.getActivityDefinition().getActType());
		model.setWf_procDefId(activityInstanceModel.getProcDefId());
		model.setWf_procDefKey(uniteworkTask.getProcDefKey());
		model.setWf_procDefName(uniteworkTask.getProcDefName());
		model.setWf_appId(activityInstanceModel.getTenantId());
		model.setWf_procInstId(activityInstanceModel.getProcInstId());
		
		Map<String, Object> resultMap = processExecuteService.nextExecute(model);
		if(resultMap.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)resultMap.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)resultMap.get("executeErrorCode")).name() , (String)resultMap.get("executeErrorMsg"));
		}
	}
	
	@RequestMapping(value="/callback", method= RequestMethod.POST, produces="application/json; charset=UTF-8")
	public ProcessInstanceBean callBack(@RequestBody ProcessInputModel model) {
		String curActInstId = model.getWf_curActInstId();
		if(RestUtils.isEmpty(curActInstId)) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_curActInstId is null");
		}
		ActivityInstanceModel curActInst=processInstanceService.getHistoryTask(curActInstId);
		if(curActInst == null) {
			throw new RestException(ExceptionErrorCode.B2052.name(), "activity instance not found, id=" + curActInstId);
		}
		UniteworkTask params=new UniteworkTask();
		params.setCurActInstId(model.getWf_curActInstId());
		UniteworkTask uniteworkTask = uniteworkService.findByParams(params).get(0);
		if(uniteworkTask == null)
			throw new RestException(ExceptionErrorCode.B2052.name(), "unitework task not found, curActIndtId=" + model.getWf_curActInstId());
		if(StringUtils.isNotEmpty(model.getWf_batchId())) {
			if(model.getWf_batchId().equals("no")) {//不使用批次逻辑
				model.setWf_batchId(null);
			}else{//批次逻辑不同流程不同环节可以更改
				
			}
		}else {//批次逻辑一个流程实例沿用一套，沿用流程批次逻辑
			model.setWf_batchId(uniteworkTask.getBatchId());
		}
		String procDefId = curActInst.getProcDefId();
		model.setWf_procInstId(curActInst.getProcInstId());
		model.setWf_procDefId(curActInst.getProcDefId());
		model.setWf_procDefName(curActInst.getProcDefName());
		model.setWf_appId(curActInst.getTenantId());

		ActivityDefinitionModel curActModel = processDefinitionService.getActivity(procDefId, curActInst.getActDefId());
		if(curActModel == null) {
			throw new RestException(ExceptionErrorCode.B2003.name(), "current activity definition not found, procid=" + procDefId + ", actid=" + curActInst.getActDefId());
		}else {
			model.setWf_curActDefName(curActModel.getActDefName());
			model.setWf_curActDefType(curActModel.getActType());
		}

		ProcessDefinitionModel procDefModel = processDefinitionService.getProcessDef(procDefId);
		if(procDefModel == null) {
			throw new RestException(ExceptionErrorCode.B2002.name(), "process definition not found, id=" + procDefId);
		}
		else {
			model.setWf_procDefId(procDefModel.getProcDefId());
			model.setWf_procDefKey(procDefModel.getProcDefKey());
			model.setWf_procDefName(procDefModel.getProcDefName());
		}
		model.setWf_actionType(WorkFlowContants.ACTION_TYPE_CALLBACK_ACTIVITY);
		model.setWf_procTitle(curActInst.getProcTitle());
		Map<String, Object> resultMap = processExecuteService.nextExecute(model);
		if(resultMap.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)resultMap.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)resultMap.get("executeErrorCode")).name() , (String)resultMap.get("executeErrorMsg"));
		}
	}
	
	@RequestMapping(value="/reject", method= RequestMethod.POST, produces="application/json; charset=UTF-8")
	public ProcessInstanceBean reject(@RequestBody ProcessInputModel model){
		Map<String, Object> result = new HashMap<String, Object>();
		
		if(RestUtils.isEmpty(model.getWf_sendUserId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserId is null");
		}		
		/*if(RestUtils.isEmpty(model.getWf_sendUserOrgId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_sendUserOrgId is null");
		}
		*/
		if(RestUtils.isEmpty(model.getWf_procTitle())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_procTitle is null");
		}	
		
		model.setWf_actionType(WorkFlowContants.ACTION_TYPE_REJECT_ACTIVITY);
		ActivityInstanceModel curActInst = processInstanceService.getTask(model.getWf_curActInstId());
		if(curActInst == null) 
			throw new RestException(ExceptionErrorCode.B2052.name() ,"current activity instance not found, id=" + model.getWf_curActInstId());
			
		UniteworkTask uniteworkTask = uniteworkService.getByActInstId(model.getWf_curActInstId());
		if(uniteworkTask == null)
			throw new RestException(ExceptionErrorCode.B2052.name(), "unitework task not found, curActIndtId=" + model.getWf_curActInstId());
		else
			model.setWf_batchId(uniteworkTask.getBatchId());
		model.setWf_procInstId(curActInst.getProcInstId());
		model.setWf_procDefId(curActInst.getProcDefId());
		model.setWf_procDefKey(uniteworkTask.getProcDefKey());
		model.setWf_procDefName(curActInst.getProcDefName());
		model.setWf_appId(curActInst.getTenantId());	
		model.setWf_curActDefId(curActInst.getActDefId());

		if(RestUtils.isEmpty(model.getWf_curActDefId()))
			throw new IllegalArgumentException("curActDefId is null");
		ActivityDefinitionModel curActModel = processDefinitionService.getActivity(model.getWf_procDefId(), model.getWf_curActDefId());
		if(curActModel == null) {
			throw new RestException(ExceptionErrorCode.B2003.name(), "current activity definition not found, procid=" + model.getWf_procDefId() + ",actid=" + model.getWf_curActDefId());
		}else {
			model.setWf_curActDefName(curActModel.getActDefName());
			model.setWf_curActDefType(curActModel.getActType());
		}
	
		if(!RestUtils.isEmpty(model.getWf_nextActDefId())) {
			ActivityDefinitionModel destActModel = processDefinitionService.getActivity(model.getWf_procDefId(), model.getWf_nextActDefId());
			model.setWf_nextActDefName(destActModel.getActDefName());
			model.setWf_nextActDefType(destActModel.getActType());
		}

		result = processExecuteService.nextExecute(model);
		if(result.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)result.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)result.get("executeErrorCode")).name() , (String)result.get("executeErrorMsg"));
		}
	}
	
	
	@RequestMapping(value="/singal", method= RequestMethod.POST, produces="application/json; charset=UTF-8")
	public ProcessInstanceBean singal(@RequestBody ProcessInputModel model){
		Map<String, Object> result = new HashMap<String, Object>();
		
		if(RestUtils.isEmpty(model.getWf_procTitle())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_procTitle is null");
		}	
		model.setWf_actionType(WorkFlowContants.ACTION_TYPE_SIGNAL_RECEIVE_ACTIVITY);
		result = processExecuteService.nextExecute(model);
		if(result.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)result.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)result.get("executeErrorCode")).name() , (String)result.get("executeErrorMsg"));
		}
	}	
	
	@ResponseBody
	@RequestMapping(value="/transfer", method= RequestMethod.POST, produces="application/json; charset=UTF-8")
	public ProcessInstanceBean transfer(@RequestBody ProcessInputModel model) {
		Map<String, Object> result = new HashMap<String, Object>();
		
		if(RestUtils.isEmpty(model.getWf_curActInstId())) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "wf_curActInstId is null");
		}
		
		ActivityInstanceModel actInst=processInstanceService.getTask(model.getWf_curActInstId());
		if(actInst==null){
			throw new RestException(ExceptionErrorCode.B2052.name(), "current activity instance not found, id=" + model.getWf_curActInstId());
		}
		//List<ActivityReceiverModel> activityReceiverModels=new ArrayList<ActivityReceiverModel>();
		//activityReceiverModels.add(new ActivityReceiverModel(actInst.getReceiverUserId(),actInst.getReceiverUserName(),actInst.getReceiverOrgId(),actInst.getReceiverOrgName()));
		ProcessInputModel processInputModel =(ProcessInputModel) processInstanceService.getTaskVariables(actInst.getActInstId()).get(WorkFlowContants.WF_PROCESS_INPUT_VARIABLE_KEY);
		//processInputModel.setWf_receiver(receivers);
		processInputModel.setWf_receivers(model.getWf_receivers());
		processInputModel.setWf_sender(actInst.getReceiver());
		processInputModel.setWf_sendUserId(actInst.getReceiverUserId());
		processInputModel.setWf_sendUserOrgId(actInst.getReceiverOrgId());
		processInputModel.setWf_actionType(WorkFlowContants.ACTION_TYPE_RECEIVER_TRANSFER);
		processInputModel.setWf_curActInstId(actInst.getActInstId());
		processInputModel.setWf_curActDefId(actInst.getActivityDefinition().getActDefId());
		processInputModel.setWf_curActDefName(actInst.getActivityDefinition().getActDefName());
		processInputModel.setWf_procDefId(actInst.getProcDefId());
		processInputModel.setWf_procTitle(actInst.getProcTitle());
		processInputModel.setWf_procInstId(actInst.getProcInstId());
		processInputModel.setWf_curComment(model.getWf_curComment());
		result = processExecuteService.nextExecute(processInputModel);
		if(result.get("processInstanceModel") != null) {
			ProcessInstanceModel instance = (ProcessInstanceModel)result.get("processInstanceModel");
			return beansBuilder.build(instance);
		}else {
			throw new RestException(((ExceptionErrorCode)result.get("executeErrorCode")).name() , (String)result.get("executeErrorMsg"));
		}
	}
	
	@RequestMapping(value="/{actInstId}/claim/{sender}", method= RequestMethod.GET, produces="application/json; charset=UTF-8")
	public boolean claim(@PathVariable String actInstId, @PathVariable String sender) {
		Map<String, Object> result = new HashMap<String, Object>();
		if(RestUtils.isEmpty(actInstId)||RestUtils.isEmpty(sender)) {
			throw new RestException(ExceptionErrorCode.B2001.name(), "actInst or sender is null");
		}
		ActivityInstanceModel actInst=processInstanceService.getTask(actInstId);
		if(actInst==null){
			throw new RestException(ExceptionErrorCode.B2052.name(), "current activity instance not found, id=" + actInstId);
		}
		if(!actInst.getReceiver().equals(sender)) {
			throw new RestException(ExceptionErrorCode.B2052.name(), "current sender not power, id=" + actInstId);
		}
		processInstanceService.getTaskService().updateOwner(actInstId, sender);
		return true;
	}
	
	

	@RequestMapping(value = "/{procInstId}/claimActivities/{actDefId}/{owner}", produces = "application/json; charset=UTF-8")
	public Map<String, Object> findclaimActivities(@PathVariable String procInstId, @PathVariable String actDefId,
			@PathVariable String owner) {
		boolean claimFlag = false;
		HistoricTaskInstance claimTask = null;
		List<HistoricTaskInstance> historicTaskInstances = processInstanceService.getHistoryService()
				.createHistoricTaskInstanceQuery().processInstanceId(procInstId).taskDefinitionKey(actDefId).unfinished().list();
		for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
			if (StringUtils.isNoneEmpty(historicTaskInstance.getOwner())) {
				if(historicTaskInstance.getOwner().equals(owner)) {
					claimFlag = true;
				}	
				claimTask = historicTaskInstance;
				break;
			}
		}
		Map<String, Object> result = Maps.newHashMap();
		result.put("claimFlag", claimFlag);
		result.put("claimTask", claimTask);
		return result;
	}

	@ResponseBody
	@RequestMapping(value="/isTodoUser/{curActInstId}/{userId}", method= RequestMethod.GET)
	public boolean transfer(@PathVariable String curActInstId, @PathVariable String userId) {
		if(StringUtils.isEmpty(curActInstId) || StringUtils.isEmpty(userId)){
			return false;
		}
		// 越权校验，流程提交人是否为当前待办审核员
		TaskEntity task = (TaskEntity) taskService.createTaskQuery()
				.taskId(curActInstId).taskAssignee(userId)
				.singleResult();
		if (null != task) {
			return true;
		}
		return false;
	}

	/*
	@RequestMapping(value = "/myStartRecordlist", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	public Page<UniteworkTask> myStartRecordlist(@RequestBody UniteworkTask task) {
		if (task.getPageSize() == 0)
			task.setPageNumber(10);
		if (RestUtils.isEmpty(task.getStartUserId()))
			throw new RestException(ExceptionErrorCode.B2001.name(),	"startUserId is empty");
		
		return processInstanceService.queryTask(task);
	}*/

	/*
	@RequestMapping(value = "/myStartRecordcount", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
	public Map<String, Object> myStartRecordcount(@RequestBody UniteworkTask task) {
		if (RestUtils.isEmpty(task.getRecUserId()))
			throw new RestException(ExceptionErrorCode.B2001.name(),	"recUserId is empty");
		if (RestUtils.isEmpty(task.getStatus()))
			throw new RestException(ExceptionErrorCode.B2001.name(),	"status is empty");
		int count = uniteworkService.getTaskCount(task);
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("count", count);
		return result;
	}*/
	
//	
//	@RequestMapping(value="/runtime/processinstance/getoppower", produces="application/json; charset=UTF-8")
//	public List<ActivityOpBean> getOpPower(String actInstId, String scope) {
//		List<ActivityOpBean> result = new ArrayList<ActivityOpBean>();
//		Map<String, Object> pageDetailVaribale  = new HashMap<String, Object>();
//		ActivityInstanceModel actInst = processInstanceService.getTask(actInstId);
//		ActivityInfoConfig actInfo = processConfigServce.getActivityInfoConfig(actInst.getProcDefId(), actInst.getActDefId(), scope, pageDetailVaribale);
//		return beansBuilder.buildActOpList(actInfo.getActivityOperatePowers());
//	}
//	
//	
//	@RequestMapping(value="/runtime/processinstance/execute", method=RequestMethod.POST, produces="application/json;charset=UTF-8")
//	public Map<String,Object> excute(@RequestBody ProcessInputModel inputModel){
//		return processExecuteService.nextExecute(inputModel);
//	}
//	
//	@RequestMapping(value="/runtime/processinstance/getallcomment", produces="application/json; charset=UTF-8")
//	public List<ProcessLogModel> getAllComment(@RequestParam String procInstId){
//		return processInstanceService.getProcessComments(procInstId);
//	}
//	
//	@RequestMapping(value="/runtime/processinstance/test", produces="application/json; charset=UTF-8")
//	public ProcessInputModel test(){
//		ProcessInputModel model = new ProcessInputModel();
//		BusinessDataObject obj = new BusinessDataObject();
//		obj.setBizData("<xml><xml>");
//		obj.setObjectType("DEMO");
//		model.setWf_businessDataObject(obj);
//		return model;
//	}
}
