package com.tykj.workflowcore.workflow_editer.service.impl;

import com.tykj.workflowcore.base.result.ApiException;
import com.tykj.workflowcore.base.util.FileUtil;
import com.tykj.workflowcore.base.util.SpringBeanService;
import com.tykj.workflowcore.user.service.CenterUserService;
import com.tykj.workflowcore.workflow_editer.dao.FlowsInfoMapper;
import com.tykj.workflowcore.workflow_editer.entity.*;
import com.tykj.workflowcore.workflow_editer.entity.vo.*;
import com.tykj.workflowcore.workflow_editer.listener.ProcessEndListener;
import com.tykj.workflowcore.workflow_editer.service.FlowInfoService;
import com.tykj.workflowcore.workflow_editer.service.UserService;
import com.tykj.workflowcore.workflow_editer.service.WorkFlowService;
import com.tykj.workflowcore.workflow_editer.util.UserServiceBeanUtil;
import com.tykj.workflowcore.workflow_editer.validate.ProcessValidatorFactoryExt;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricActivityInstanceQuery;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.validation.ProcessValidator;
import org.flowable.validation.ValidationError;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * ClassName:    FlowableServiceImpl
 * Package:    com.tykj.service
 * Description:
 * Datetime:    2021/2/23   13:46
 *
 * @Author: zsp
 */
@Service
@Slf4j
public class WorkFlowServiceImpl implements WorkFlowService {

    private static String ALL_USER = "ALL_USER";
    private static String XML_FILE_PATH = File.separator+"xml"+File.separator;
//    private static String XML_FILE_PATH = File.separator+"xml"+File.separator;
    private static String BASE_PATH = System.getProperty("user.dir");
    private final RepositoryService repositoryService;
    private final RuntimeService runtimeService;
    private final TaskService taskService;
    private final FlowsInfoMapper flowsInfoMapper;
    private final UserService userService;
    private final HistoryService historyService;
    private final ProcessEngineConfigurationImpl processEngineConfiguration;
    private final ProcessEngine processEngine;

    final
    ProcessValidatorFactoryExt processValidatorFactoryExt;

    final
    ClassLoader classLoader;

    final
    ProcessEndListener processEndListener;

    @Autowired
    FlowInfoService flowInfoService;

    @Autowired
    CenterUserService centerUserService;

    public WorkFlowServiceImpl(SpringBeanService springBeanService, HistoryService historyService, RepositoryService repositoryService, RuntimeService runtimeService, TaskService taskService, FlowsInfoMapper flowsInfoMapper, ProcessEngineConfigurationImpl processEngineConfiguration, ProcessEngine processEngine, ClassLoader classLoader, ProcessValidatorFactoryExt processValidatorFactoryExt, ProcessEndListener processEndListener) {
        this.historyService = historyService;
        this.repositoryService = repositoryService;
        this.runtimeService = runtimeService;
        this.taskService = taskService;
        this.flowsInfoMapper = flowsInfoMapper;
        this.userService = UserServiceBeanUtil.getUserService(springBeanService);
        this.processEngineConfiguration = processEngineConfiguration;
        this.processEngine = processEngine;
        this.classLoader = classLoader;
        System.out.println(userService != null ? "成功" : "失败");
        this.processValidatorFactoryExt = processValidatorFactoryExt;
        this.processEndListener = processEndListener;
    }

    @Override
    public String upLoadFile(@RequestParam("file") MultipartFile file) {
        String realPath = null;
        if (!file.isEmpty()) {
            //获取文件名
            String fileName = file.getOriginalFilename();
            System.out.println(fileName);
            //获取文件后缀
            String suffixName = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf("."));
            //重新生成文件名
            fileName = UUID.randomUUID() + suffixName;
            System.out.println(fileName);
            //指定本地存入路径
            File fileNew = new File(classLoader.getResource("").getPath() + fileName);
            realPath = classLoader.getResource("").getPath() + fileName;
            try {
                file.transferTo(fileNew);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return realPath;
    }


    @Override
    public void flowXml(@RequestBody FlowsInfoVo flowsInfoVo) throws XMLStreamException, IOException {
        Optional<FlowsInfo> byId = flowsInfoMapper.findById(flowsInfoVo.getId());
        if(!byId.isPresent()){
            throw new ApiException("该流程不存在");
        }
        FlowsInfo flowsInfo = byId.get();
        if (flowsInfo.getState()==0){
            throw new ApiException("请先暂停流程再进行编辑");
        }
        String flowKey = flowsInfoVo.getFlowKey();
        String flowXmlResourceName = flowKey + "bpmn20.xml";
        String CustomFlowXmlResourceName = flowKey + "bpmnCustom20.xml";
        //从数据库里查处来
        if (StringUtils.isEmpty(flowsInfo.getFilePath())){
            //生成xml文件
            flowsInfo = flowsInfoVo.toEntity(flowsInfo);
            flowsInfo.setResourceName(flowXmlResourceName);
            flowsInfo.setFilePath(XML_FILE_PATH + flowXmlResourceName);
            flowsInfo.setFileCustomPath(XML_FILE_PATH + CustomFlowXmlResourceName);
        }
        File file = FileUtil.createFileByString(BASE_PATH + XML_FILE_PATH + flowXmlResourceName,
                flowsInfoVo.getFileXml().replaceAll("\\[\\?\\?[^\\]]+\\?\\?\\]", "").replaceAll("&lt;","<").replaceAll("&gt;",">"));
        FileUtil.createFileByString(BASE_PATH + XML_FILE_PATH + CustomFlowXmlResourceName, flowsInfoVo.getFileXml());
        //获取bmpnModel
        BpmnModel bpmnModel = getBpmnModel(file);
        //获取流程中所有的页面ID
        List<String> pageIds = getPageIds(bpmnModel);
        flowsInfo.setPageIds(pageIds.toString());
        //设置开始节点id
        flowsInfo.setStartPageId(getStartPageId(bpmnModel));
        //进行第一次的校验
        checkXml(bpmnModel);
        //自动部署
        deployXml(flowsInfo.getId());
        //更新并保存
        flowsInfoMapper.save(flowsInfo);
    }

    public List<String> getPageIds(BpmnModel bpmnModel){
        ArrayList<String> result = new ArrayList<>();
        List<Process> processes = bpmnModel.getProcesses();
        for (Process process : processes) {
            Collection<FlowElement> flowElements = process.getFlowElements();
            for (FlowElement flowElement : flowElements) {
                if (flowElement instanceof StartEvent){
                    result.add(((StartEvent) flowElement).getFormKey());
                }
                if (flowElement instanceof UserTask){
                    result.add(((UserTask) flowElement).getFormKey());
                }
            }
        }
        return result;
    }


    /**
     * 获取流程开始页面的ID
     * @param bpmnModel
     * @return
     */
    public Integer getStartPageId(BpmnModel bpmnModel){
        Process process = bpmnModel.getProcesses().get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();
        for (FlowElement flowElement : flowElements) {
            if (flowElement instanceof StartEvent){
                String formKey = ((StartEvent) flowElement).getFormKey();
                if (formKey == null){
                    throw new ApiException("开始节点表单不能为空");
                }else {
                    return Integer.valueOf(formKey);
                }
            }
        }
        return -1;
    }


    /**
     * 获取bpmnModel
     * @param xmlFile
     * @return
     * @throws FileNotFoundException
     * @throws XMLStreamException
     */
    public BpmnModel getBpmnModel(File xmlFile) throws FileNotFoundException, XMLStreamException {
        InputStream inputStream = new FileInputStream(xmlFile);
        BpmnXMLConverter converter = new BpmnXMLConverter();
        XMLInputFactory factory = XMLInputFactory.newInstance();
        //createXmlStreamReader
        XMLStreamReader reader = factory.createXMLStreamReader(inputStream);
        //将xml文件转换成BpmnModel
        return converter.convertToBpmnModel(reader);
    }


    public void checkXml(BpmnModel bpmnModel){
        //做校验
        ProcessValidator defaultProcessValidator = processValidatorFactoryExt.createDefaultProcessValidator();
        List<ValidationError> validate = defaultProcessValidator.validate(bpmnModel);
        StringBuffer message = new StringBuffer();
        if (validate.size()!=0){
            for (int i =0;i<validate.size();i++){
                ValidationError validationError = validate.get(i);
                String problem = validationError.getProblem();
                message.append(i+1+""+problem);
                message.append("\r\n");
            }
            throw new ApiException(null,message.toString());
        }
    }


    @Override
    public Integer createFlow(FlowsInfo flowsInfo) {
        flowsInfo.setCreatedTime(new Date());
        FlowsInfo flowsInfo1 = flowsInfoMapper.save(flowsInfo);
        return flowsInfo1.getId();
    }


    @Override
    public void deployXml(Integer id) {
        FlowsInfo flowsInfo = flowsInfoMapper.findById(id).get();
        Deployment deploy = null;
        try {
            deploy = repositoryService.createDeployment().addInputStream(System.getProperty("user.dir") + flowsInfo.getResourceName(),
                    new FileInputStream(System.getProperty("user.dir") + flowsInfo.getFilePath())).deploy();

        } catch (Exception e) {
            throw new ApiException("流程图不符合规范");
        }
        //将流程自动挂起
        repositoryService.suspendProcessDefinitionByKey(flowsInfo.getFlowKey(), true, new Date());
        //修改状态
        flowsInfo.setState(1);
        flowsInfo.setDeployId(deploy.getId());
        flowsInfoMapper.save(flowsInfo);

    }

    @Override
    public void startFlow(@RequestBody StartFlowVo startFlowVo) {
        //设置流程发起人
        WorkFlowUser currentUser = userService.getCurrentUser();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(startFlowVo.getFlowKey(),currentUser.getId(),
                startFlowVo.getMap());
//        存储流程实例id
//        根据flowKey查询出一个FlowInfo
//        FlowsInfo flowsInfo = flowsInfoMapper.findByFlowKey(startFlowVo.getFlowKey());
        //开始页面的id
//        Integer startPageId = flowsInfo.getStartPageId();
//        flowsInfo.setProcessInstanceId(processInstance.getProcessInstanceId());
//        flowsInfoMapper.save(flowsInfo);
//        return startPageId;
    }


    @Override
    public List<Map<String, Object>> findTaskByUserId(NextTaskVo nextTaskVo) {
        List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>();
        TaskQuery taskQuery = taskService.createTaskQuery();
        if (nextTaskVo.getGroupStrings() != null || nextTaskVo.getUserId() != null) {
            if (!StringUtils.isEmpty(nextTaskVo.getProcessName())){
                taskQuery.processDefinitionName("%"+nextTaskVo.getProcessName()+"%");
            }
            if (!StringUtils.isEmpty(nextTaskVo.getTaskName())) {
                taskQuery.taskName("%"+nextTaskVo.getTaskName()+"%");
            }
            taskQuery.or();
            taskQuery.taskCandidateUser(ALL_USER);
            if (nextTaskVo.getUserId() != null) {
                taskQuery.taskCandidateUser(nextTaskVo.getUserId());
            }
            if (nextTaskVo.getGroupStrings() != null && nextTaskVo.getGroupStrings().size() > 0) {
                taskQuery.taskCandidateGroupIn(nextTaskVo.getGroupStrings());
            }
            taskQuery.endOr();

        }
        taskQuery.orderByTaskCreateTime().desc();
        List<Task> listTask = taskQuery.list();
        DataHistory dataHistory = new DataHistory();
        for (Task task : listTask) {
            Map<String, Object> map = new HashMap<>();
            ProcessInstance processInstance =
                    runtimeService.createProcessInstanceQuery()
                            .processInstanceId(task.getProcessInstanceId())
                            .singleResult();
            //节点id
            String taskDefinitionKey = task.getTaskDefinitionKey();
            //通过节点id查询出pageId
//            Integer currentPageId = nodeInfoService.findByNodeId(taskDefinitionKey);
            FlowsInfo byFlowKeyWithDelete = flowInfoService.findByFlowKeyWithDelete(processInstance.getProcessDefinitionKey());
            //节点id  formkey
            String formKey = task.getFormKey();
            map.put("taskId", task.getId());
            map.put("processKey", processInstance.getProcessDefinitionKey());
            map.put("taskName", task.getName());
            map.put("taskDesc", task.getDescription());
            map.put("createTime", task.getCreateTime());
            map.put("promoter", processInstance.getStartUserId());
            map.put("processInstanceId", processInstance.getId());
            map.put("currentPageId", formKey);
            map.put("processName", processInstance.getProcessDefinitionName());
            if (byFlowKeyWithDelete!=null){
                map.put("processDes", byFlowKeyWithDelete.getFlowDescribe());
            }


            listMap.add(map);
        }
        return listMap;

    }

    @Override
    public Map<String, Object> findTaskDetail(String taskId) {
        Map<String, Object> variables = new HashMap<>();
        //流程还在运行
        if (taskId != null) {
            variables = taskService.getVariables(taskId);
        } else {
            //流程已经结束
            //从历史中查询
            HistoricTaskInstance historicTaskInstance =
                    historyService.createHistoricTaskInstanceQuery().taskId(taskId).finished().singleResult();
            variables.put("historicTaskInstance", historicTaskInstance);
        }
        return variables;
    }

    @Override
    public void completeTask(@RequestBody TaskVo taskVo) {

        ConcurrentHashMap oldFlowMap = new ConcurrentHashMap<>();
        ConcurrentHashMap userMap = new ConcurrentHashMap<>();
        Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
        if (task==null){
            throw new ApiException(null,"该任务已经被完成了");
        }

        //用户map
        if (taskVo.getMap()!=null){
            userMap.putAll(taskVo.getMap());
        }
        //流程map
        oldFlowMap.putAll(taskService.getVariables(taskVo.getTaskId()));
        String processInstanceId = task.getProcessInstanceId();
        Map<String, Object> localMap = new HashMap<>();
        //如果 存在任务评论的话 向任务中添加任务评论
        if (taskVo.getComments() != null) {
            taskService.addComment(task.getId(), processInstanceId, taskVo.getComments());
        }
        //先判断
        if (taskVo.getHandlingOpinion() != null){
            //局部变量
           localMap.put("handlingOpinion",taskVo.getHandlingOpinion());
        }
        try {
            taskService.setVariables(task.getId(),userMap);
            claimTask(task.getId());
            taskService.complete(task.getId(),localMap);
        } catch (Exception e) {
            e.printStackTrace();
            taskService.removeVariableLocal(task.getId(),"handlingOpinion");
            taskService.removeVariables(task.getId(),taskService.getVariables(task.getId()).keySet());
            taskService.setVariables(task.getId(),oldFlowMap);
            //归还
            taskService.setAssignee(task.getId(),null);
        }
    }

    @Override
    public void claimTask(String taskId) {
        //当前登录人的Id
        taskService.claim(taskId, userService.getCurrentUser().getId());
    }

    @Override
    public void transferTask(TransferTask transferTask) {
        taskService.setAssignee(transferTask.getTaskId(), transferTask.getUserId());
    }


    @Override
    public void suspendOrActivateProcessDefinitionByKey(Integer id) {
        //通过流程ID 查询出flowsInfo
        FlowsInfo flowsInfo = flowsInfoMapper.findById(id).get();
        String flowKey = flowsInfo.getFlowKey();
        List<Deployment> list = repositoryService.createDeploymentQuery().processDefinitionKey(flowKey).list();
        if (list != null && list.size() > 0) {
            //部署
            if (flowsInfo.getState() == 0) {
                //挂起
                repositoryService.suspendProcessDefinitionByKey(flowKey, true, new Date());
                flowsInfo.setState(1);
            } else {
                //激活
                repositoryService.activateProcessDefinitionByKey(flowKey, true, new Date());
                flowsInfo.setState(0);
            }
        } else {
            deployXml(id);
        }
        flowsInfoMapper.save(flowsInfo);
    }


    @Override
    public void deleteFlow(Integer id) {
        //通过流程id查询出flowsInfo
        Optional<FlowsInfo> flowsInfoMapperById = flowsInfoMapper.findById(id);
        if (flowsInfoMapperById.isPresent()) {
            FlowsInfo flowsInfo = flowsInfoMapperById.get();
            if (flowsInfo.getDeleted() == 0) {
                flowsInfoMapper.deleteById(id);
            }
        } else {
            throw new ApiException(null,"流程不存在");
        }

    }

    @Override
    public void flowProgress(HttpServletResponse httpServletResponse, String processId) throws IOException {
//
//        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
//        //流程走完的不显示图
//        if (pi == null) {
//            return;
//        }
//        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
//        //使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
//        String processInstanceId = task.getProcessInstanceId();
//        List<Execution> executions = runtimeService
//                .createExecutionQuery()
//                .processInstanceId(processInstanceId)
//                .list();
//
//        //得到正在执行的Activity的Id
//        List<String> activityIds = new ArrayList<>();
//        List<String> flows = new ArrayList<>();
//        for (Execution exe : executions) {
//            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
//            activityIds.addAll(ids);
//        }
//
//        //获取流程图
//        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
//        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
//        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
//        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, true);
//        OutputStream out = null;
//        byte[] buf = new byte[1024];
//        int legth = 0;
//        try {
//            out = httpServletResponse.getOutputStream();
//            while ((legth = in.read(buf)) != -1) {
//                out.write(buf, 0, legth);
//            }
//        } finally {
//            if (in != null) {
//                in.close();
//            }
//            if (out != null) {
//                out.close();
//            }
//        }

    }

    @Override
    public PageReturnVo<List<TaskHistoryReturnVo>> findHistoryTask(MyTaskSelectVo myTaskSelectVo) {
        //拼接processInstance查询器
//        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
//        historicProcessInstanceQuery.processInstanceBusinessKey(myTaskSelectVo.getUserId());
//        List<HistoricProcessInstance> myStartProcessInstance = historicProcessInstanceQuery.list();
//        //根据processInstance查询出所有开始节点的信息
//        List<HistoricActivityInstance> userHistoricStartActivityInstance = new ArrayList<>();
//        for (HistoricProcessInstance historicProcessInstance : myStartProcessInstance) {
//            HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
//            historicActivityInstanceQuery.processInstanceId(historicProcessInstance.getId());
//            if (!StringUtils.isEmpty(myTaskSelectVo.getTaskName())){
//            }
//            List<HistoricActivityInstance> startEvent = historyService.createHistoricActivityInstanceQuery()
//                    .processInstanceId(historicProcessInstance.getId())
//                    .activityType("startEvent")
//                    .list();
//        }
        //由于这里存在两种数据的查询 无法正常分页 所以需要一点特殊的手段
        //前区的偏移
        long offset1 = 0 ;
        long size1 = 0 ;
        //后区偏移
        long offset2 = 0 ;
        long size2 = 0 ;
        //计算分页信息
        long count1 = historyService.createHistoricProcessInstanceQuery()
                .processInstanceBusinessKey(myTaskSelectVo.getUserId())
                .count();
        long count2 = historyService
                .createHistoricActivityInstanceQuery()
                .activityType("userTask")
                .taskAssignee(userService.getCurrentUser().getId() + "")
                .finished()
                .orderByHistoricActivityInstanceStartTime()
                .desc()
                .count();
        long allCount = count1 + count2;
        long pageOffset = myTaskSelectVo.getOffset();
        long pageSize = myTaskSelectVo.getSize();
        //先判断偏移量是否超出前区
        if (pageOffset>count1){
            offset2 = pageOffset - count1;
            size2 = pageSize;
        }else {
            offset1 = pageOffset;
            size1 = count1 - pageOffset;
            pageSize = pageSize - size1;
            size2 = pageSize;
        }
        // 流程名称 任务名称 流程状态 发起人  办理人 办理时间
        List<TaskHistoryReturnVo> taskHistoryReturnVoList = new ArrayList<>();
        //查出我发起的流程
        List<HistoricProcessInstance> myStartProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceBusinessKey(myTaskSelectVo.getUserId())
                .listPage((int) offset1,(int) size1);
        //先查出所有的开始节点  拼接节点信息
        //由于开始节点也存在内容，所有需要将开始节点的内容放入返回集
        for (HistoricProcessInstance historicProcessInstance : myStartProcessInstance) {
            //开始节点有且仅有一个
            List<HistoricActivityInstance> startEvent = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(historicProcessInstance.getId())
                    .activityType("startEvent")
                    .list();
            HistoricActivityInstance historicActivityInstance = startEvent.get(0);
            //查出对应的流程信息
            String processDefinitionKey = historicProcessInstance.getProcessDefinitionKey();
            FlowsInfo byFlowKeyWithDelete = flowInfoService.findByFlowKeyWithDelete(processDefinitionKey);
            TaskHistoryReturnVo taskHistoryReturnVo = new TaskHistoryReturnVo();
            taskHistoryReturnVo.setTaskName(historicActivityInstance.getActivityName());
            taskHistoryReturnVo.setCreateTime(historicActivityInstance.getStartTime());
            taskHistoryReturnVo.setEndTime(historicActivityInstance.getEndTime());
            if (historicActivityInstance.getEndTime()==null){
                taskHistoryReturnVo.setState(0);
            }else {
                taskHistoryReturnVo.setDurationTime(getDatePoor(historicActivityInstance.getEndTime(),historicActivityInstance.getStartTime()));
                taskHistoryReturnVo.setState(1);
            }
            taskHistoryReturnVo.setProcessDescription(byFlowKeyWithDelete.getFlowDescribe());
            taskHistoryReturnVo.setProcessName(byFlowKeyWithDelete.getFlowName());
            //流程的开启人，就是任务的执行人
            taskHistoryReturnVo.setCreateUser(centerUserService.findById(historicProcessInstance.getBusinessKey()).getRealName());
            taskHistoryReturnVo.setId(historicActivityInstance.getId());
            taskHistoryReturnVo.setProcessInstanceId(historicProcessInstance.getId());
            taskHistoryReturnVoList.add(taskHistoryReturnVo);
        }
        //查出我执行的任务，并添加到最后返回的列表
        List<HistoricActivityInstance> taskInstanceList =
                historyService
                        .createHistoricActivityInstanceQuery()
                        .activityType("userTask")
                        .taskAssignee(userService.getCurrentUser().getId()+"")
                        .finished()
                        .orderByHistoricActivityInstanceStartTime()
                        .desc()
                        .listPage((int) offset2,(int) size2);
        //遍历将我执行的任务都加入到返回列表中
        for (HistoricActivityInstance historicActivityInstance : taskInstanceList) {
            //查出对应的流程实例 有且只有一个
            List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(historicActivityInstance.getProcessInstanceId())
                    .list();
            HistoricProcessInstance historicProcessInstance = list.get(0);
            //查出对应的流程信息
            String processDefinitionKey = historicProcessInstance.getProcessDefinitionKey();
            FlowsInfo byFlowKeyWithDelete = flowInfoService.findByFlowKeyWithDelete(processDefinitionKey);
            //拼接对应的任务信息
            TaskHistoryReturnVo taskHistoryReturnVo = new TaskHistoryReturnVo();
            taskHistoryReturnVo.setTaskName(historicActivityInstance.getActivityName());
            taskHistoryReturnVo.setCreateTime(historicActivityInstance.getStartTime());
            taskHistoryReturnVo.setEndTime(historicActivityInstance.getEndTime());
            if (historicActivityInstance.getEndTime()==null){
                taskHistoryReturnVo.setState(0);
            }else {
                taskHistoryReturnVo.setDurationTime(getDatePoor(historicActivityInstance.getEndTime(),historicActivityInstance.getStartTime()));
                taskHistoryReturnVo.setState(1);
            }
            taskHistoryReturnVo.setProcessDescription(byFlowKeyWithDelete.getFlowDescribe());
            taskHistoryReturnVo.setProcessName(byFlowKeyWithDelete.getFlowName());
            //流程的开启人，就是任务的执行人
            taskHistoryReturnVo.setCreateUser(centerUserService.findById(historicProcessInstance.getBusinessKey()).getRealName());
            taskHistoryReturnVo.setId(historicActivityInstance.getId());
            taskHistoryReturnVo.setProcessInstanceId(historicProcessInstance.getId());
            taskHistoryReturnVoList.add(taskHistoryReturnVo);
        }


//        List<HistoricActivityInstance> taskInstanceList =
//                historyService
//                        .createHistoricActivityInstanceQuery()
//                        .taskAssignee(userService.getCurrentUser().getId()+"")
//                        .finished()
//                        .orderByHistoricActivityInstanceStartTime()
//                        .desc()
//                        .list();
//        ArrayList<Object> arrayList = new ArrayList<>();
//        arrayList.addAll(taskInstanceList);
        return new PageReturnVo<>(allCount,taskHistoryReturnVoList

        );
    }

    @Override
    public String getCurrentNodeId(String taskId) {
        if (taskId!=null){
            return taskService.createTaskQuery().taskId(taskId).singleResult().getTaskDefinitionKey();
        }else {
            throw new ApiException(null,"任务已经不存在了");
        }

    }

    @Override
    public String getCurrentProcId(String taskId) {

        return null;
    }

    @Override
    public PageReturnVo<List<ProcessInstanceReturnVo> > findStartByUser(MyStartProcessSelectVo myStartProcessSelectVo) {
        //先获取流程的BusinessKey
        List<HistoricProcessInstance> historicProcessInstances = null;
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
            historicProcessInstanceQuery.processInstanceBusinessKey(myStartProcessSelectVo.getUserId());
            if (myStartProcessSelectVo.getState()!=null){
                if (myStartProcessSelectVo.getState()==0){
                    historicProcessInstanceQuery.unfinished();
                }
                if (myStartProcessSelectVo.getState()==1){
                    historicProcessInstanceQuery.finished();
                }
            }
            if (!StringUtils.isEmpty(myStartProcessSelectVo.getProcessName())){
                historicProcessInstanceQuery.processDefinitionName("%"+myStartProcessSelectVo.getProcessName()+"%");
            }
        historicProcessInstances = historicProcessInstanceQuery.listPage((int) myStartProcessSelectVo.getOffset(), myStartProcessSelectVo.getLimit());
//                .processInstanceBusinessKey(myStartProcessSelectVo.getUserId()).list();
        List<ProcessInstanceReturnVo> processInstanceReturnVos = new ArrayList<>();
        //拼接VO 流程名称 流程描述 流程状态 状态 创建时间 创建人 完成时间 持续时间
        for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
            ProcessInstanceReturnVo processInstanceReturnVo = new ProcessInstanceReturnVo();
            String processDefinitionKey = historicProcessInstance.getProcessDefinitionKey();
            //查出对应的流程信息
            FlowsInfo byFlowKeyWithDelete = flowInfoService.findByFlowKeyWithDelete(processDefinitionKey);
            processInstanceReturnVo.setProcessName(byFlowKeyWithDelete.getFlowName());
            processInstanceReturnVo.setProcessDescription(byFlowKeyWithDelete.getFlowDescribe());
            processInstanceReturnVo.setCreateTime(historicProcessInstance.getStartTime());
            processInstanceReturnVo.setEndTime(historicProcessInstance.getEndTime());
            processInstanceReturnVo.setProcessInstanceId(historicProcessInstance.getId());
            if (processInstanceReturnVo.getEndTime()==null){
                processInstanceReturnVo.setState(0);
            }else {
                processInstanceReturnVo.setDurationTime(getDatePoor(processInstanceReturnVo.getEndTime(),processInstanceReturnVo.getCreateTime()));
                processInstanceReturnVo.setState(1);
            }
            processInstanceReturnVo.setCreateUser(centerUserService.findById(historicProcessInstance.getBusinessKey()).getRealName());
            //将processInstanceReturnVo 加入到返回的数组中
            processInstanceReturnVos.add(processInstanceReturnVo);
        }
        return new PageReturnVo<List<ProcessInstanceReturnVo> >(historicProcessInstanceQuery.count(),processInstanceReturnVos);
    }

    /**
     * 计算 两个时间相差多少
     * @param endDate
     * @param nowDate
     * @return
     */
    public String getDatePoor(Date endDate, Date nowDate) {

        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }



    @Override
    public Map<String, Object> setVariables(@RequestBody Map<String, Object> maxMap) {
        Map<String, Object> map = new HashMap<>();
        map.putAll(maxMap);
        return map;
    }

    @Override
    public void stopProcessInstanceById(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance != null) {
            //1、获取终止节点
            List<EndEvent> endNodes =findEndFlowElement(processInstance.getProcessDefinitionId());
            String endId = endNodes.get(0).getId();
            //2、执行终止
            List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
            List<String> executionIds = new ArrayList<>();
            executions.forEach(execution -> executionIds.add(execution.getId()));
            runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState();
            log.info("终止processInstanceId:{}胜利",processInstanceId);
        }else {
            log.info("不存在运行的流程实例processInstanceId:{},请确认!",processInstanceId);
        }
    }

    public List findEndFlowElement(String processDefId) {
        Process mainProcess = repositoryService.getBpmnModel(processDefId).getMainProcess();
        Collection<FlowElement> list = mainProcess.getFlowElements();
        if (CollectionUtils.isEmpty(list)) {
            return Collections.EMPTY_LIST;
        }
        return list.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList());
    }

    @Override
    public List<ProcessInstance> queryUnfinishedProcessInstance(String processKey){
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processDefinitionKey(processKey).list();
        return list;
    }

    public HistoricActivityInstance findLastActivityByProcessInstance(String processInstance){
        List<HistoricActivityInstance> list = historyService
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processInstance)
                .orderByHistoricActivityInstanceStartTime()
                .finished()
                .desc()
                .list();
        //根据降序遍历 返回符合条件的第一个
        for (HistoricActivityInstance historicActivityInstance : list) {
            if (historicActivityInstance.getActivityType().equals("userTask")){
                return historicActivityInstance;
            }
            if (historicActivityInstance.getActivityType().equals("startEvent")){
                return historicActivityInstance;
            }
        }
        return list.get(0);
    }

    @Override
    public HistoricActivityInstance findActivityById(String Id) {
        List<HistoricActivityInstance> list =
                historyService
                        .createHistoricActivityInstanceQuery()
                        .activityInstanceId(Id)
                        .list();
        if (list!=null&&list.size()>0){
            return list.get(0);
        }else {
            return null;
        }
    }


}
