package com.ruoyi.flowable.service.impl;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.service.IFlowService;
import com.ruoyi.flowable.service.ISysFormService;
import com.ruoyi.flowable.service.ISysTaskFormService;
import org.flowable.engine.*;
import org.flowable.engine.form.FormProperty;
import org.flowable.engine.impl.form.StartFormDataImpl;
import org.flowable.engine.impl.form.TaskFormDataImpl;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class FlowServiceImpl extends FlowServiceFactory implements IFlowService {

	@Autowired
    private TaskService taskService;
	@Autowired
    private HistoryService historyService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private FormService formService;
    @Autowired
	private IdentityService identityService;
    @Autowired
    private RepositoryService repositoryService;
	@Autowired
	private ISysFormService sysFormService;

    /**
     * 根据任务Id获取流程实例信息
     */
	@Override
    public ProcessInstance getProcessInstance(String taskId){
    	
    	ProcessInstance pInstan = null;
    	try{
    		Task task = taskService.createTaskQuery().taskId(taskId).active().singleResult();
    		
    		if(task != null){
    			String processInstanceId = task.getProcessInstanceId();
    			
    			pInstan = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
    		}
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    	
    	return pInstan;
    }
    
    /**
     * 根据任务对象获取流程实例信息
     */
	@Override
    public ProcessInstance getProcessInstance(Task task){
    	
    	ProcessInstance pInstan = null;
    	
    	try{
    		if(task != null){
    			String processInstanceId = task.getProcessInstanceId();
    			
    			pInstan = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
    		}
    		
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    	
    	return pInstan;
    }
    
    /**
     * 获取节点的formkey值
     */
	/*@Override
    public String getFormKey(String pInstId, String taskId, String opType){
    	
    	String formKey = "";
    	
    	if(StringUtils.isNotBlank(pInstId)) {
    		if(StringUtils.isNotBlank(taskId)){
    			formKey = formService.getTaskFormKey(pInstId, taskId);
    		}
    		// 如果指定的任务没有设置 formkey, 则取表单开始节点设置的 formkey
    		if(StringUtils.isBlank(formKey) || "detail".equals(opType)){
    			formKey = formService.getStartFormKey(pInstId);
    			
    			if(StringUtils.isNotBlank(formKey)){
    				
    				*//**
    				 *  以流程开始节点为基准, 根据opType参数和固定的规则来构建 表单请求路径
    				 *//*
    				
    				// 申请表单 -- 因为开始节点设置的 formkey 就是申请表单，所以暂时不需要处理
    				if(AcOperateTypeEnum.CREATE.eq(opType)){
    					
    				}else if(AcOperateTypeEnum.DETAIL.eq(opType)){ // 表单详情
    					int index = formKey.lastIndexOf("/");
    					formKey = formKey.substring(0, index) + "/detail";
    				}else if(AcOperateTypeEnum.AUDIT.eq(opType)){ // 表单审核
    					int index = formKey.lastIndexOf("/");
    					formKey = formKey.substring(0, index) + "/audit";
    				}
    			}
    		}
    	}
    	
    	return formKey;
    }*/
    
    /**
     * 获取表单信息, 如果 taskId 不为空则获取指定taskId的表单，否则就根据pDefId获取流程开始节点定义的表单
     */
    @SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> getFormProperties(String pDefId, String taskId){
    	
    	Map<String, Object> rs = new HashMap<>();
    	
    	try{
    		
    		List<FormProperty> formProperties = null;
    		
    		if(StringUtils.isNotBlank(taskId)) {
    			TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId);
    			// 设置task为null，否则输出json的时候会报错
    	        taskFormData.setTask(null);
    	        
    	        formProperties = taskFormData.getFormProperties();
    			
    			rs.put("form", taskFormData);
    			
    		} else if(StringUtils.isNotBlank(pDefId)){
    			StartFormDataImpl startFormData = (StartFormDataImpl) formService.getStartFormData(pDefId);
    			startFormData.setProcessDefinition(null);
    			
    			formProperties = startFormData.getFormProperties();
    			
    			rs.put("form", startFormData);
    		}
    		
    		if(formProperties != null){
    			for (FormProperty formProperty : formProperties) {
    	            Map<String, String> values = (Map<String, String>) formProperty.getType().getInformation("values");
    	            
    	            if (values != null) {
    	                for (Map.Entry<String, String> enumEntry : values.entrySet()) {
    	                }
    	                rs.put(formProperty.getId(), values);
    	            }
    	        }
    		}
    		
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    	
    	return rs;
    }
    
    /**
     * 给指定的表单map赋值,并返回 表单form的字符串表示形式
     */

	@Override
	public String getFormProperties(Map<String, Object> fpMap, Map<String, String[]> mapParams) {
    	
    	String fpMapStr = "";
    	
    	try {
    		
    		if(fpMap != null && mapParams != null){
    			
    			ObjectMapper objMapper = new ObjectMapper();
    			fpMapStr = objMapper.writeValueAsString(fpMap);
    			
    			Map<String, Object> fpMapNew = objMapper.readValue(fpMapStr, Map.class);
    			
    			Object oFormMap = fpMapNew.get("form");
    			if(oFormMap != null){
    				
    				Map<String, Object> formMap = (Map<String, Object>)oFormMap;
    				Object oFormProperties = formMap.get("formProperties");
    				if(oFormProperties != null){
    					List<Map<String, Object>> lstFpMap = (List<Map<String, Object>>)oFormProperties;
    					
    					for(Map<String, Object> fp : lstFpMap){
    						String id = "fp_" + fp.get("id").toString();
    						
    						if(mapParams.containsKey(id)){
    							fp.put("value", mapParams.get(id)[0]);
    						}
    					}
    				}
    			}
    			
    			return objMapper.writeValueAsString(fpMapNew);
    		}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
    	
    	return fpMapStr;
    }
	@Override
	public Map<String, Object> taskComplete(String taskId, boolean isOk, Map<String, Object> map, String loginId) throws Exception {

		Map<String, Object> rs = new HashMap<String, Object>();

		rs.put("status", false);

		Map<String, Object> formProperties = new HashMap<String, Object>();
		TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId);

		if (taskFormData != null) {
			// 设置task为null，否则输出json的时候会报错
			taskFormData.setTask(null);

			List<FormProperty> lstFormProperties = taskFormData.getFormProperties();
			if (lstFormProperties != null) {
				for (FormProperty formProperty : lstFormProperties) {
					if (!formProperty.isWritable()) {
						continue;
					}
					formProperties.put(formProperty.getId(), formProperty.getValue());
				}
			}
		}

		for (Map.Entry<String, Object> mm : map.entrySet()) {
			formProperties.put(mm.getKey(), mm.getValue());
		}
		// 从request中读取参数然后转换
		formProperties.put("isOk", String.valueOf(isOk));

		try {
			// 设置审批人，以及提交审批信息
			identityService.setAuthenticatedUserId(loginId);
			taskService.complete(taskId, formProperties);
//        	formService.submitTaskFormData(taskId, formProperties);
			rs.put("status", true);
			// String msg = isOk ? "审核完成，同意成功!" : "审核完成，驳回成功!";
			String msg = "审核完成!";
			rs.put("msg", msg);
			//更新代办任务数量
			sysFormService.updateToDoNumber();
		} catch (Exception e) {
			e.printStackTrace();
			rs.put("status", false);
			rs.put("msg", "审核失败!");
		} finally {
			identityService.setAuthenticatedUserId(null);
		}

		return rs;
	}

	/**
	 *
	 * @Description (跳转任意目标节点)
	 * @author liuwei
	 * @Date 2021年11月3日上午10:23:00
	 * @version 1.0.0
	 * @param map
	 *            taskId，destTaskKey，rejectMessage，outcome
	 */
	/*@Override
	public void skipStipulationTask(Map<String, Object> map) {
		String taskId = (String) map.get("taskId");
		// 目标任务key
		String destTaskKey = (String) map.get("destTaskKey");
		//审批消息
		String rejectMessage = (String) map.get("rejectMessage");
		//流程线
		String outcome = (String) map.get("outcome");
		//业务的用户ID
		String uid = (String) map.get("uid");
		//审批消息
		String message = (String) map.get("message");
		// 使用任务ID，获取任务信息
		Task taskEntity = taskService.createTaskQuery().taskId(taskId).singleResult();
		// 获得当前任务的流程实例ID
		String processInstanceId = taskEntity.getProcessInstanceId();

		// 获得当前任务的流程定义ID
		String processDefinitionId = taskEntity.getProcessDefinitionId();
		// 当前任务key
		String currtaskDefKey = taskEntity.getTaskDefinitionKey();

		// 获得当前活动节点和驳回的目标节点"draft"
		ActivityImpl currActiviti = null;// 当前活动节点
		ActivityImpl destActiviti = null;// 驳回目标节点

		currActiviti = getActivityImpl(currtaskDefKey, processDefinitionId);
		destActiviti = getActivityImpl(destTaskKey, processDefinitionId);

		// 保存当前活动节点的流程流出参数

		List<PvmTransition> hisPvmTransitionList = new ArrayList<PvmTransition>(0);

		for (PvmTransition pvmTransition : currActiviti.getOutgoingTransitions()) {
			hisPvmTransitionList.add(pvmTransition);
		}
		// 清空当前活动节点的所有流出项

		currActiviti.getOutgoingTransitions().clear();
		// 为当前节点动态创建新的流出项

		TransitionImpl newTransitionImpl = currActiviti.createOutgoingTransition();
		// 为当前活动节点新的流出项指定为目标流程节点
		newTransitionImpl.setDestination(destActiviti);
		// 保存驳回意见
		taskEntity.setDescription(rejectMessage);// 设置驳回意见
		taskService.saveTask(taskEntity);

		*//**
		 * 注意：添加批注的时候，由于Activiti底层代码是使用： String userId =
		 * Authentication.getAuthenticatedUserId(); CommentEntity comment = new
		 * CommentEntity(); comment.setUserId(userId);
		 * 所有需要从Session中获取当前登录人，作为该任务的办理人（审核人），对应act_hi_comment表中的User_ID的字段，
		 * 不添加审核人，该字段为null
		 * 所以要求，添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人
		 *//*
		Authentication.setAuthenticatedUserId(uid);
		taskService.addComment(taskId, processInstanceId, message);

		// 设定驳回标志
		Map<String, Object> variables = new HashMap<String, Object>(0);
		variables.put("outcome", outcome);
		// 执行当前任务驳回到目标任务draft
		taskService.complete(taskEntity.getId(), variables);
		// 清除目标节点的新流入项
		destActiviti.getIncomingTransitions().remove(newTransitionImpl);
		// 清除原活动节点的临时流程项
		currActiviti.getOutgoingTransitions().clear();
		// 还原原活动节点流出项参数
		currActiviti.getOutgoingTransitions().addAll(hisPvmTransitionList);
	}*/

	/**
	 *
	 * @Description (通过任务key,获取对应的节点信息)
	 * @author liuwei
	 * @Date 2021年11月3日下午1:53:29
	 * @version 1.0.0
	 * @param destTaskKey
	 * @param processDefinitionId
	 * @return
	 */
	/*public ActivityImpl getActivityImpl(String destTaskKey, String processDefinitionId) {
		// 获得当前流程的定义模型
		ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(processDefinitionId);

		// 获得当前流程定义模型的所有任务节点

		List<ActivityImpl> activitilist = processDefinition.getActivities();
		// 获得当前活动节点和驳回的目标节点"draft"
		ActivityImpl descActiviti = null;// 当前活动节点

		for (ActivityImpl activityImpl : activitilist) {
			// 获取节点对应的key
			String taskKey = activityImpl.getId();
			// 确定当前活动activiti节点
			if (destTaskKey.equals(taskKey)) {
				descActiviti = activityImpl;
				break;
			}
		}
		return descActiviti;
	}*/
}
