package org.springblade.flow.engine.custom.graph;


import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.SequenceFlow;

import static org.springblade.flow.base.util.BpmnModelUtils.getBpmnModelMainProcess;

import java.util.HashSet;
import java.util.Set;


/**
 * 根据流程定义，构建设计阶段的图.
 */
public class ActivitiGraphBuilder {
    /**
     * 流程定义id.
     */
    private String processDefinitionId;

    /**
     * 流程定义.
     */
    private Process processDefinitionEntity;

    /**
     * 已访问的节点id.
     */
    private Set<String> visitedNodeIds = new HashSet<String>();

    /**
     * 构造方法.
     */
    public ActivitiGraphBuilder(String processDefinitionId) {
        this.processDefinitionId = processDefinitionId;
    }

    /**
     * 构建图.
     */
    public Graph build() {
        this.fetchProcessDefinitionEntity();

        Node initial = visitNode((FlowNode) processDefinitionEntity.getInitialFlowElement());

        Graph graph = new Graph();
        graph.setInitial(initial);

        return graph;
    }

    /**
     * 获取流程定义.
     */
    public void fetchProcessDefinitionEntity() {
        Process process = getBpmnModelMainProcess(processDefinitionId);

    }

    /**
     * 遍历.
     */
    public Node visitNode(FlowNode pvmActivity) {
        if (visitedNodeIds.contains(pvmActivity.getId())) {
            return null;
        }

        visitedNodeIds.add(pvmActivity.getId());

        Node currentNode = new Node();
        currentNode.setId(pvmActivity.getId());
        currentNode.setName(this.getString(pvmActivity.getName()));
        currentNode.setType(this.getString(parseActivityType(pvmActivity)));

        for (SequenceFlow pvmTransition : pvmActivity.getOutgoingFlows()) {
            FlowNode destination = (FlowNode) pvmTransition.getTargetFlowElement();
            Node targetNode = this.visitNode(destination);

            if (targetNode == null) {
                continue;
            }

            Edge edge = new Edge();
            edge.setId(pvmTransition.getId());
            edge.setSrc(currentNode);
            edge.setDest(targetNode);
            currentNode.getOutgoingEdges().add(edge);
        }

        return currentNode;
    }

    /**
     * 把object转换为string.
     */
    public String getString(Object object) {
        if (object == null) {
            return null;
        } else if (object instanceof String) {
            return (String) object;
        } else {
            return object.toString();
        }
    }

    protected String parseActivityType(FlowElement element) {
        String elementType = element.getClass().getSimpleName();
        elementType = elementType.substring(0, 1).toLowerCase() + elementType.substring(1);
        return elementType;
    }
}
