package cn.datax.service.workflow.service.impl;

import cn.datax.service.workflow.api.query.DefinitionQuery;
import cn.datax.service.workflow.service.ProcessDefinitionService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipInputStream;

@Service
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {

    @Autowired
    private RepositoryService repositoryService;

    public static final String BPMN20_FILE_SUFFIX = ".bpmn20.xml";
    public static final String RESOURCE_TYPE_IMAGE = "image";
    public static final String RESOURCE_TYPE_XML = "xml";

    @Override
    public void page(DefinitionQuery definitionQuery) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        if (StrUtil.isNotBlank(definitionQuery.getName())) {
            processDefinitionQuery.processDefinitionNameLike(definitionQuery.getName());
        }
        if(StringUtils.isNotBlank(definitionQuery.getKey())){
            processDefinitionQuery.processDefinitionKeyLike(definitionQuery.getKey());
        }
        if(StringUtils.isNotBlank(definitionQuery.getCategoryId())){
            processDefinitionQuery.processDefinitionCategory(definitionQuery.getCategoryId());
        }
        long count = processDefinitionQuery.count();
        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage((definitionQuery.getPageNum() - 1) * definitionQuery.getPageSize(), definitionQuery.getPageSize());
        Page<ProcessDefinition> page = new Page<>(definitionQuery.getPageNum(), definitionQuery.getPageSize());
        page.setRecords(processDefinitionList);
        page.setTotal(count);
    }

    @Override
    public void deploy(String name, String category, String tenantId, InputStream in) {
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        deploymentBuilder.addInputStream(name + BPMN20_FILE_SUFFIX, in);
        deploymentBuilder.name(name);
        if (StrUtil.isNotBlank(tenantId)) {
            deploymentBuilder.tenantId(tenantId);
        }
        if (StrUtil.isNotBlank(category)) {
            deploymentBuilder.category(category);
        }
        Deployment deployment = deploymentBuilder.deploy();
    }

    @Override
    public void deploy(String name, String category, String tenantId, ZipInputStream zipInputStream) {
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        deploymentBuilder.addZipInputStream(zipInputStream);
        deploymentBuilder.name(name);
        if (StrUtil.isNotBlank(tenantId)) {
            deploymentBuilder.tenantId(tenantId);
        }
        if (StrUtil.isNotBlank(category)) {
            deploymentBuilder.category(category);
        }
        Deployment deployment = deploymentBuilder.deploy();
    }

    @Override
    public void activateProcessDefinitionById(String processDefinitionId) {
        repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
    }

    @Override
    public void suspendProcessDefinitionById(String processDefinitionId) {
        repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
    }

    @Override
    public void deleteDeployment(String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
    }

    @Override
    public InputStream resource(String processDefinitionId, String resType) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        String resourceName = "";
        if (RESOURCE_TYPE_IMAGE.equals(resType)) {
            resourceName = processDefinition.getDiagramResourceName();
        } else if (RESOURCE_TYPE_XML.equals(resType)) {
            resourceName = processDefinition.getResourceName();
        }
        InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        return resourceAsStream;
    }
}
