package com.jeeplus.flowable.service;

import cn.hutool.core.collection.CollectionUtil;
import org.apache.commons.lang.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.RepositoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Service
public class FlowableBpmnModelService {
    @Autowired
    private RepositoryService repositoryService;

    public BpmnModel getBpmnModelByProcessDefId(String processDefId) {
        return repositoryService.getBpmnModel ( processDefId );
    }

    public List <FlowNode> findFlowNodes(String processDefId) {
        List <FlowNode> flowNodes = new ArrayList <> ( );
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId ( processDefId );
        Process process = bpmnModel.getMainProcess ( );
        Collection <FlowElement> list = process.getFlowElements ( );
        list.forEach ( flowElement -> {
            if ( flowElement instanceof FlowNode ) {
                flowNodes.add ( (FlowNode) flowElement );
            }
        } );
        return flowNodes;
    }

    public List <EndEvent> findEndFlowElement(String processDefId) {
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId ( processDefId );
        if ( bpmnModel != null ) {
            Process process = bpmnModel.getMainProcess ( );
            return process.findFlowElementsOfType ( EndEvent.class );
        } else {
            return null;
        }
    }

    public FlowNode findMainProcessActivityByActivityId(String processDefId, String activityId) {
        FlowNode activity = null;
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId ( processDefId );
        Process process = bpmnModel.getMainProcess ( );
        FlowElement flowElement = process.getFlowElement ( activityId );
        if ( flowElement != null ) {
            activity = (FlowNode) flowElement;
        }
        return activity;
    }

    public FlowNode findFlowNodeByActivityId(String processDefId, String activityId) {
        FlowNode activity = null;
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId ( processDefId );
        List <Process> processes = bpmnModel.getProcesses ( );
        for (Process process : processes) {
            FlowElement flowElement = process.getFlowElementMap ( ).get ( activityId );
            if ( flowElement != null ) {
                activity = (FlowNode) flowElement;
                break;
            }
        }
        return activity;
    }

    public boolean checkActivitySubprocessByActivityId(String processDefId, String activityId) {
        boolean flag = true;
        List <FlowNode> activities = this.findFlowNodesByActivityId ( processDefId, activityId );
        if ( CollectionUtil.isNotEmpty ( activities ) ) {
            flag = false;
        }
        return flag;
    }

    public List <FlowNode> findFlowNodesByActivityId(String processDefId, String activityId) {
        List <FlowNode> activities = new ArrayList <> ( );
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId ( processDefId );
        List <Process> processes = bpmnModel.getProcesses ( );
        for (Process process : processes) {
            FlowElement flowElement = process.getFlowElement ( activityId );
            if ( flowElement != null ) {
                FlowNode flowNode = (FlowNode) flowElement;
                activities.add ( flowNode );
            }
        }
        return activities;
    }

    public List <Activity> findActivityByActivityId(String processDefId, String activityId) {
        List <Activity> activities = new ArrayList <> ( );
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId ( processDefId );
        List <Process> processes = bpmnModel.getProcesses ( );
        for (Process process : processes) {
            FlowElement flowElement = process.getFlowElement ( activityId );
            if ( flowElement != null ) {
                Activity activity = (Activity) flowElement;
                activities.add ( activity );
            }
        }
        return activities;
    }

    public Activity findActivityByName(String processDefId, String name) {
        Activity activity = null;
        BpmnModel bpmnModel = this.getBpmnModelByProcessDefId ( processDefId );
        Process process = bpmnModel.getMainProcess ( );
        Collection <FlowElement> list = process.getFlowElements ( );
        for (FlowElement f : list) {
            if ( StringUtils.isNotBlank ( name ) ) {
                if ( name.equals ( f.getName ( ) ) ) {
                    activity = (Activity) f;
                    break;
                }
            }
        }
        return activity;
    }
}
