package com.zkqy.common.utils.bpm;

import cn.hutool.core.util.XmlUtil;
import com.zkqy.common.utils.uuid.IdUtils;
import org.w3c.dom.*;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 解析流程xml工具类
 */
public class XmlDataParserUtils {

    /**
     * 解析流程xml文件内容，得到开始节点和下一个节点
     *
     * @param xmlData xml内容
     * @return
     */
    public static Map<String,String> getStartNodeAndNextNode(String xmlData){
        Map<String, String> map = new HashMap<>();
        Document document= XmlUtil.parseXml(xmlData);
        //获得XML文档根节点
        Element elementG=XmlUtil.getRootElement(document);
        //获取bpmn:process节点
        Element bpmnProcessEvent = XmlUtil.getElement(elementG,"bpmn:process");
        //获取开始节点并得到开始节点ID
        Element bpmnStartEvent=XmlUtil.getElement(bpmnProcessEvent,"bpmn:startEvent");
        String startNode = bpmnStartEvent.getAttribute("id");
        map.put("startNode",startNode);

        //获取所有序列流（顺序）,循环得到开始节点的下一个节点
        NodeList elementsByTagName = elementG.getElementsByTagName("bpmn:sequenceFlow");
        for (int i = 0; i < elementsByTagName.getLength(); i++) {
            if (startNode.equals(elementsByTagName.item(i).getAttributes().getNamedItem("sourceRef").getNodeValue())) {
                map.put("nextNode",elementsByTagName.item(i).getAttributes().getNamedItem("targetRef").getNodeValue());
                break;
            }
        }
        return map;
    }

    /**
     * 新增用户异常节点
     * @param userTaskTagName 新增节点名称
     * @param nextTagId 新增节点下一节点ID
     * @return
     */
    public static String addUserTaskTag(String xmlData,String newUserTaskTagId,String userTaskTagName,String nextTagId) throws Exception {
        //新增节点标签ID
//        String newUserTaskTagId = "Flow_" + IdUtils.fastSimpleUUID().substring(0,7);
        //新增序列流ID
        String newSequenceFlowId = "Flow_" + IdUtils.fastSimpleUUID().substring(0,7);
        //新增节点下一节点序列流ID
        String sequenceFlowId = null;
        //上一节点标签ID
        String previousId = null;
        //将xml文件内容转成Document对象
        Document document= XmlUtil.parseXml(xmlData);
        //获得XML文档根节点
        Element elementG=XmlUtil.getRootElement(document);
        //获取所有序列流（顺序）,循环得到新增节点下一节点序列流ID、上一节点标签ID,修改新增节点下一节点序列流sourceRef为新增节点标签ID
        NodeList elementsByTagName = elementG.getElementsByTagName("bpmn:sequenceFlow");
        for (int i = 0; i < elementsByTagName.getLength(); i++) {
            if (nextTagId.equals(elementsByTagName.item(i).getAttributes().getNamedItem("targetRef").getNodeValue())) {
                sequenceFlowId = elementsByTagName.item(i).getAttributes().getNamedItem("id").getNodeValue();
                previousId = elementsByTagName.item(i).getAttributes().getNamedItem("sourceRef").getNodeValue();
                //获取当前元素
                Node node = elementsByTagName.item(i);
                //创建一个新的Attr对象，并设置新的属性值
                Attr newAttr = document.createAttribute("sourceRef");
                newAttr.setValue(newUserTaskTagId);
                node.getAttributes().setNamedItem(newAttr);
                break;
            }
        }
        //创建异常任务节点标签
        Element userTaskTag = document.createElement("bpmn:exceptionTask");
        userTaskTag.setAttribute("id",newUserTaskTagId);
        userTaskTag.setAttribute("name",userTaskTagName);
        userTaskTag.appendChild(document.createTextNode("\n\t\t"));
        Element userTaskTagChild1 = document.createElement("bpmn:incoming");
        userTaskTagChild1.setTextContent(newSequenceFlowId);
        userTaskTag.appendChild(userTaskTagChild1);
        userTaskTag.appendChild(document.createTextNode("\n\t\t"));
        Element userTaskTagChild2 = document.createElement("bpmn:outgoing");
        userTaskTagChild2.setTextContent(sequenceFlowId);
        userTaskTag.appendChild(userTaskTagChild2);
        userTaskTag.appendChild(document.createTextNode("\n\t"));
        //创建新序列流标签
        Element sequenceFlowTag = document.createElement("bpmn:sequenceFlow");
        sequenceFlowTag.setAttribute("id",newSequenceFlowId);
        sequenceFlowTag.setAttribute("sourceRef",previousId);
        sequenceFlowTag.setAttribute("targetRef",newUserTaskTagId);
        //修改上一节点bpmn:outgoing和下一节点bpmn:incoming
        //获取bpmn:process节点
        Element bpmnProcessEvent = XmlUtil.getElement(elementG,"bpmn:process");
        NodeList bpmnProcessNextLevelEventList = bpmnProcessEvent.getChildNodes();
        for (int i = 0; i < bpmnProcessNextLevelEventList.getLength(); i++) {
            Node node = bpmnProcessNextLevelEventList.item(i);
            //判断node是元素节点，并且是Element实例
            if (node.getNodeType() == Node.ELEMENT_NODE && node instanceof Element) {
                Element element = (Element) node;
                String id = element.getAttribute("id");
                if(id.equals(previousId)){
                    Element elementOutgoing = XmlUtil.getElement(element,"bpmn:outgoing");
                    elementOutgoing.setTextContent(newSequenceFlowId);
                }
                if(id.equals(nextTagId)){
                    Element elementOutgoing = XmlUtil.getElement(element,"bpmn:incoming");
                    elementOutgoing.setTextContent(sequenceFlowId);
                    //插入标签
                    Node parentNode = element.getParentNode();
                    parentNode.insertBefore(userTaskTag,element);

                    parentNode.insertBefore(sequenceFlowTag,element);
                }
            }
        }
        //将document对象转成字符串
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource source = new DOMSource(document);
        StreamResult result = new StreamResult(new StringWriter()); // 使用StringWriter来将结果输出为字符串
        transformer.transform(source, result);
        String data = result.getWriter().toString();
        return data;
    }

    /**
     * 获取下一节点key
     * @param xmlData xml内容
     * @param taskNodeKey 当前节点key
     * @return
     */
    public static String getNextNodeKey(String xmlData, String taskNodeKey){
        //下一节点key
        String nextTaskNodeKey = null;
        Document document= XmlUtil.parseXml(xmlData);
        //获得XML文档根节点
        Element elementG=XmlUtil.getRootElement(document);
        //获取所有序列流（顺序）,循环得到开始节点的下一个节点
        NodeList elementsByTagName = elementG.getElementsByTagName("bpmn:sequenceFlow");
        for (int i = 0; i < elementsByTagName.getLength(); i++) {
            if(taskNodeKey.equals(elementsByTagName.item(i).getAttributes().getNamedItem("sourceRef").getNodeValue())){
                nextTaskNodeKey = elementsByTagName.item(i).getAttributes().getNamedItem("targetRef").getNodeValue();
            }
        }
        return nextTaskNodeKey;
    }

}
