package com.huigou.explorer.converters.mxgraph;

import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.util.mxDomUtils;
import com.mxgraph.view.mxGraph;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.springframework.util.Assert;
import org.w3c.dom.Element;

/**
 * @author yonghuan
 */
public abstract class AbstractMxVertexConverter extends AbstractMxElementConverter implements MxElementConverter {

    @Override
    public void convert(BpmnModel bpmnModel, Process process, mxGraph graph, BaseElement baseElement) {
        FlowElement fe = (FlowElement) baseElement;
        Element valueWrapper = mxDomUtils.createDocument().createElement("object");
        GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(fe.getId());
        mxGraphModel graphModel = (mxGraphModel) graph.getModel();
        mxCell rootCell = (mxCell) graphModel.getRoot();
        Assert.isTrue(rootCell.getChildCount() == 1, "root cell 只能拥有一个子cell");
        mxCell vertex = (mxCell) graph.insertVertex(rootCell.getChildAt(0), fe.getId(), valueWrapper, graphicInfo.getX(), graphicInfo.getY(), graphicInfo.getWidth(), graphicInfo.getHeight());
        vertex.setAttribute("code", fe.getId());
        vertex.setAttribute("label", fe.getName());
        parseExecutionListeners(fe, vertex);
        convertInternal(bpmnModel, process, graph, fe, vertex);
        if (fe instanceof FlowNode) {
            FlowNode flowNode = (FlowNode) baseElement;
            vertex.setAttribute("asynchronous", String.valueOf(flowNode.isAsynchronous()));
            vertex.setAttribute("exclusive", String.valueOf(!flowNode.isNotExclusive()));
        }
        if (fe instanceof Activity) {
            Activity activity = (Activity) fe;
            MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics();
            if (multiInstanceLoopCharacteristics != null) {
                vertex.setAttribute("multiInstanceType", multiInstanceLoopCharacteristics.isSequential() ? "sequential" : "parallel");
                vertex.setAttribute("multiInstanceCollection", multiInstanceLoopCharacteristics.getInputDataItem());
                vertex.setAttribute("multiInstanceCardinality", multiInstanceLoopCharacteristics.getLoopCardinality());
                vertex.setAttribute("multiInstanceElementVariable", multiInstanceLoopCharacteristics.getElementVariable());
                vertex.setAttribute("multiInstanceCompletionCondition", multiInstanceLoopCharacteristics.getCompletionCondition());
            }
            if (activity.isForCompensation()) {
                vertex.setAttribute("isForCompensation", "true");
            }
        }
    }

    /**
     * 驼峰命名转换为下划线命名
     *
     * @param camelCase 驼峰命名
     * @return 下划线命名
     */
    protected String camelCaseToUnderscoreCase(String camelCase) {
        StringBuilder underscoreCase = new StringBuilder();
        int idx = 0;
        for (char ch : camelCase.toCharArray()) {
            if (idx++ > 0 && ch >= 'A' && ch <= 'Z') {
                underscoreCase.append("_");
            }
            underscoreCase.append(Character.toLowerCase(ch));
        }
        return underscoreCase.toString();
    }

    protected abstract void convertInternal(BpmnModel bpmnModel, Process process, mxGraph graph, FlowElement fe, mxCell vertex);
}
