package com.activiti6.controller.activiti;


import com.activiti6.common.utils.StringUtils;
import com.activiti6.config.img.ProcessDiagramGenarateExt;
import com.activiti6.domain.*;
import com.activiti6.domain.form.MyFormDataActivitiForm;
import com.activiti6.domain.form.TaskDoneListForm;
import com.activiti6.domain.form.TaskListForm;
import com.activiti6.service.activiti.LeaveNewService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 请假业务Controller
 *
 * @author Xianlu Tech
 * @date 2019-10-11
 */
@RestController
@RequestMapping("/leaveNew")
public class LeaveNewController extends BaseController {
    @Autowired
    private LeaveNewService leaveNewService;

    /**
     * 更具流程key获取开始表单key
     *
     * @param processKey
     * @return
     */
    @GetMapping("/processKey/{processKey}/{userId}")
    @ResponseBody
    public AjaxResult getFormData(@PathVariable("processKey") String processKey, @PathVariable("userId") Long userId) {

        return AjaxResult.success(leaveNewService.getFormData(processKey, userId));
    }

    /**
     * 提交表单
     *
     * @param myFormDataActiviti
     * @return
     */
    @PutMapping
    @ResponseBody
    public AjaxResult add(@RequestBody MyFormDataActivitiForm myFormDataActivitiForm) {
        MyFormDataActiviti myFormDataActiviti = myFormDataActivitiForm.getMyFormDataActiviti();
        SysUser user = myFormDataActivitiForm.getUser();
        Long userId = user.getUserId();
        myFormDataActiviti.setApplyUser(userId.toString());
        myFormDataActiviti.setCreateUser(user.getNickName());
        myFormDataActiviti.setCreateDept(user.getDept().getDeptName());
        myFormDataActiviti.setCreateBy(userId.toString());
        myFormDataActiviti.setCreateTime(new Date());
        return AjaxResult.success(leaveNewService.add(myFormDataActiviti, userId));
    }


    @GetMapping("/list")
    @ResponseBody
    public TableDataInfo list(Long userId) {
        startPage();
        List<MyFormDataActiviti> list = leaveNewService.select(userId);
        return getDataTable(list);
    }

    @GetMapping("/task")
    @ResponseBody
    public AjaxResult task(String id) {
        List<MyTaskVo> list = leaveNewService.taskList(id);
        return AjaxResult.success(list);
    }

    @GetMapping("/{id}")
    @ResponseBody
    public AjaxResult get(@PathVariable("id") Long id) {
        MyFormDataActiviti myFormDataActiviti = leaveNewService.get(id);
        return AjaxResult.success(myFormDataActiviti);
    }

    @GetMapping("/showForms/{instanceId}")
    @ResponseBody
    public AjaxResult showForms(@PathVariable("instanceId") String instanceId) {
        List<FormsVo> list = leaveNewService.showForms(instanceId);
        return AjaxResult.success(list);
    }

    @PostMapping
    @ResponseBody
    public AjaxResult update(@RequestBody MyFormDataActivitiForm myFormDataActivitiForm) {
        return toAjax(leaveNewService.update(myFormDataActivitiForm.getMyFormDataActiviti(),myFormDataActivitiForm.getUser().getUserId()));
    }

    /**
     * 删除请假业务
     */

    @DeleteMapping
    @ResponseBody
    public AjaxResult remove(@RequestBody List<Long> ids) {
        return toAjax(leaveNewService.remove(ids));
    }

    /**
     * 提交申请
     *
     * @param id
     * @return
     */
    @PostMapping("/submitApply/{id}/{userId}")
    @ResponseBody
    public AjaxResult submitApply(@PathVariable("id") Long id, @PathVariable("userId") Long userId) {
        leaveNewService.submitApply(id, userId);
        return AjaxResult.success();
    }

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;


//    @RequestMapping(value = "/read-resource")
//    public void readResource(@RequestParam("processDefinitionKey") String processDefinitionKey, @RequestParam("version") Integer version, @RequestParam("processInstanceId") String processInstanceId, HttpServletResponse response)
//            throws Exception {
//        // 设置页面不缓存
//        showImage(processDefinitionKey, version, processInstanceId, response);
//    }

    @GetMapping(value = "/read-resource")
    public void readResource(@RequestParam("processInstanceId") String processInstanceId, HttpServletResponse response)
            throws Exception {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        getActivitiProccessImage(processInstanceId, response);

    }


    @GetMapping(value = "/read-activiti")
    public void readActiviti(@RequestParam("processDefinitionKey") String processDefinitionKey, @RequestParam("version") Integer version, HttpServletResponse response)
            throws Exception {
        // 设置页面不缓存
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();

        ProcessDefinition pd = pdq.processDefinitionKey(processDefinitionKey).processDefinitionVersion(version).singleResult();

        BpmnModel bpmnModel = repositoryService.getBpmnModel(pd.getId());

        // 获取流程图图像字符流
        // ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
        // 获取流程图图像字符流
        ProcessDiagramGenarateExt pec = new ProcessDiagramGenarateExt();
        //配置字体
        InputStream imageStream = pec.generateDiagram(bpmnModel, "png", "宋体", "宋体", "宋体", null, 2.0);

        response.setContentType("image/png");
        OutputStream os = response.getOutputStream();
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        imageStream.close();
    }

    /**
     * 查询代办事项
     *
     * @return
     */
    @GetMapping("/taskList")
    @ResponseBody
    public TableDataInfo taskList(TaskListForm taskListForm) throws InterruptedException {
        TableDataInfo tableDataInfo = leaveNewService.findTodoTasks(taskListForm,taskListForm.getUserId());
        return tableDataInfo;
    }

    @GetMapping("/task/user/{userId}")
    public AjaxResult taskUser(@PathVariable("userId") String userId) {
        return AjaxResult.success(leaveNewService.taskUserMsg(userId));
    }

    /**
     * 更具流程key获取开始表单key
     *
     * @param
     * @return
     */
    @GetMapping("/taskFormData")
    @ResponseBody
    public AjaxResult taskFormData(MyTaskVo myTaskVo) {
        MyFormData myFormData = leaveNewService.taskFormData(myTaskVo);
        return AjaxResult.success(myFormData);
    }

    /**
     * 完成task
     *
     * @return
     */
    @PostMapping("/taskCommit")
    @ResponseBody
    public AjaxResult taskCommit(@RequestBody TaskCommitForm taskCommitForm) {
        leaveNewService.taskCommit(taskCommitForm,taskCommitForm.getUser());
        return AjaxResult.success();
    }


    @GetMapping("/taskDoneList")
    @ResponseBody
    public TableDataInfo taskDoneList(TaskDoneListForm myFormDataActiviti) {
        startPage();
        List<MyFormDataActiviti> list = leaveNewService.taskDoneList(myFormDataActiviti,myFormDataActiviti.getUserId());
        return getDataTable(list);
    }

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ProcessEngine processEngine;

    private void showImage(String processDefinitionKey, Integer version, String processInstanceId, HttpServletResponse response) throws IOException {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
        ProcessDefinition pd = pdq.processDefinitionKey(processDefinitionKey).processDefinitionVersion(version).singleResult();

        String resourceName = pd.getDiagramResourceName();

        if (resourceName.endsWith(".png") && StringUtils.isEmpty(processInstanceId) == false) {
            getActivitiProccessImage(processInstanceId, response);
        }
    }


    /**
     * 获取流程图像，已执行节点和流程线高亮显示
     */
    public void getActivitiProccessImage(String processInstanceId, HttpServletResponse response) {
        //logger.info("[开始]-获取流程图图像");
        try {
            //  获取历史流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId).singleResult();

            if (historicProcessInstance == null) {
                //throw new BusinessException("获取流程实例ID[" + processInstanceId + "]对应的历史流程实例失败！");
            } else {
                // 获取流程定义
                ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                        .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());

                // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
                List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                        .processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list();
                // 已执行的节点ID集合
                List<String> executedActivityIdList = new ArrayList<String>();
                int index = 1;
                //logger.info("获取已经执行的节点ID");
                for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                    executedActivityIdList.add(activityInstance.getActivityId());
                    //logger.info("第[" + index + "]个已执行节点=" + activityInstance.getActivityId() + " : " +activityInstance.getActivityName());
                    index++;
                }

                BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());

                // 已执行的线集合
                List<String> flowIds = new ArrayList<String>();
                // 获取流程走过的线 (getHighLightedFlows是下面的方法)
                flowIds = executedFlowIdList(bpmnModel, processDefinition, historicActivityInstanceList);

                // 获取流程图图像字符流
                ProcessDiagramGenarateExt pec = new ProcessDiagramGenarateExt();

                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                boolean end = false;
                if (StringUtils.isNull(processInstance)) {
                    end = true;
                }
                //配置字体
                InputStream imageStream = pec.generateDiagram(end, bpmnModel, "png", executedActivityIdList, flowIds, "宋体", "宋体", "宋体", null, 2.0);

                response.setContentType("image/png");
                OutputStream os = response.getOutputStream();
                int bytesRead = 0;
                byte[] buffer = new byte[8192];
                while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
                os.close();
                imageStream.close();
            }
            //logger.info("[完成]-获取流程图图像");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            //logger.error("【异常】-获取流程图失败！" + e.getMessage());
            //throw new BusinessException("获取流程图失败！" + e.getMessage());
        }
    }

    private static List<String> executedFlowIdList(BpmnModel bpmnModel, ProcessDefinitionEntity processDefinitionEntity,
                                                   List<HistoricActivityInstance> historicActivityInstanceList) {

        List<String> executedFlowIdList = new ArrayList<>();


        for (int i = 0; i < historicActivityInstanceList.size() - 1; i++) {
            HistoricActivityInstance hai = historicActivityInstanceList.get(i);
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(hai.getActivityId());
            List<SequenceFlow> sequenceFlows = flowNode.getOutgoingFlows();
            if (sequenceFlows.size() > 1) {
                HistoricActivityInstance nextHai = historicActivityInstanceList.get(i + 1);
                sequenceFlows.forEach(sequenceFlow -> {
                    if (sequenceFlow.getTargetFlowElement().getId().equals(nextHai.getActivityId())) {
                        executedFlowIdList.add(sequenceFlow.getId());
                    }
                });
            } else {
                executedFlowIdList.add(sequenceFlows.get(0).getId());
            }
        }

        return executedFlowIdList;
    }

}
