package com.huigou.explorer.converters.mxgraph;

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

import java.util.List;
import java.util.stream.Collectors;

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

    @Override
    public boolean supports(BaseElement baseElement) {
        return baseElement instanceof SequenceFlow;
    }

    @Override
    public void convert(BpmnModel bpmnModel, Process process, mxGraph graph, BaseElement baseElement) {
        SequenceFlow sf = (SequenceFlow) baseElement;
        mxGraphModel graphModel = (mxGraphModel) graph.getModel();
        Element valueWrapper = mxDomUtils.createDocument().createElement("object");

        mxCell source = (mxCell) graphModel.getCell(sf.getSourceRef());
        mxCell target = (mxCell) graphModel.getCell(sf.getTargetRef());
        mxCell rootCell = (mxCell) graphModel.getRoot();
        Assert.isTrue(rootCell.getChildCount() == 1, "root cell 只能拥有一个子cell");
        mxCell edge = (mxCell) graph.insertEdge(rootCell.getChildAt(0), baseElement.getId(), valueWrapper, source, target, "edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1");
        edge.setAttribute("code", sf.getId());
        edge.setAttribute("label", sf.getName());
        edge.setAttribute("conditionExpression", sf.getConditionExpression());
        edge.setAttribute("skipExpression", sf.getSkipExpression());
        List<GraphicInfo> graphicInfos = bpmnModel.getFlowLocationGraphicInfo(sf.getId());
        if (graphicInfos != null && graphicInfos.size() > 2) {
            List<mxPoint> points = graphicInfos.stream()
                    .skip(1)
                    .limit(graphicInfos.size() - 2)
                    .map(gi -> new mxPoint(gi.getX(), gi.getY()))
                    .collect(Collectors.toList());
            if (edge.getGeometry().getPoints() != null) {
                edge.getGeometry().getPoints().addAll(points);
            } else {
                edge.getGeometry().setPoints(points);
            }
        }
        parseExecutionListeners(sf, edge);
    }
}
