package com.chinaweal.aiccs.aiccs.business.rules.parsexml;

import com.chinaweal.aiccs.aiccs.business.rules.model.SequenceFlowModel;
import com.chinaweal.aiccs.aiccs.business.rules.model.NodeModel;
import com.chinaweal.aiccs.aiccs.business.rules.model.RuleModel;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author <a href="https://blog.lroyia.top">lroyia</a>
 * @since 2021/1/29 16:42
 **/
@Slf4j
public class ParseRuleXML {

    public static RuleModel parseXML(File file) throws DocumentException {
        //监视耗时
        StopWatch clock = new StopWatch();
        clock.start();
        SAXReader saxReader = new SAXReader();
        Document document = null;
        RuleModel ruleModel = null;
        String filename = file.getAbsolutePath();
        try {
            ruleModel = new RuleModel();
            document = saxReader.read(file);
            //workflow 层
            Element root = document.getRootElement();

            String wdefinedname = root.attributeValue("definedname");
            if (StringUtils.isBlank(wdefinedname)) {
                throw new BusinessException(filename + ":中的definedname为空请检查模版。");
            }
            ruleModel.setDefinedname(wdefinedname);
            ruleModel.setDescription(root.attributeValue("description"));
            String independent = root.attributeValue("independent");
            if (StringUtils.isNotBlank(independent)) {
                ruleModel.setIndependent(Boolean.parseBoolean(independent));
            }

            //nodes 节点
            Element nodesE = root.element("nodes");
            //node 节点集合
            Iterator nodeItE = nodesE.elementIterator("node");
            Map<String, NodeModel> nodeModeMap = new LinkedHashMap<String, NodeModel>();
            NodeModel nodeModel = null;
            String nodeid = null;
            String nodename = null;
            String start = null;
            String end = null;
            String handle = null;
            boolean isStart = false;
            boolean isEnd = false;
            while (nodeItE.hasNext()) {
                nodeModel = new NodeModel();
                Element nodeE = (Element) nodeItE.next();
                nodeid = nodeE.attributeValue("id");
                if (StringUtils.isBlank(nodeid)) {
                    throw new BusinessException(filename + ":中的node.id为空请检查模版。");
                }
                nodename = nodeE.attributeValue("name");
                if (StringUtils.isBlank(nodename)) {
                    throw new BusinessException(filename + ":中的node.name为空请检查模版。");
                }
                nodeModel.setId(nodeid);
                nodeModel.setName(nodename);
                nodeModel.setDescription(nodeE.attributeValue("description"));
                start = nodeE.attributeValue("start");
                end = nodeE.attributeValue("end");
                handle = nodeE.attributeValue("handle");
                if (StringUtils.isNotBlank(start) && "true".equals(start)) {
                    if (isStart) {
                        throw new BusinessException(filename + ":中的node定义了多个开始节点请检查模版。");
                    }
                    isStart = true;
                    nodeModel.setStart(true);
                    ruleModel.setStartnodeid(nodeid);
                }
                if (StringUtils.isNotBlank(end) && "true".equals(end)) {
                    isEnd = true;
                    nodeModel.setEnd(true);
                    ruleModel.setEndnodeid(nodeid);
                }
                if (StringUtils.isNotBlank(end) && "false".equals(handle)) {
                    nodeModel.setHandle(false);
                }
                if (nodeModeMap.put(nodeid, nodeModel) != null) {
                    throw new BusinessException(filename + ":中定义的node.name重复定义，请检查模版。");
                }
            }
            if (!isStart) {
                throw new BusinessException(filename + ":中的node没有定义开始节点为空请检查模版。");
            }
            if (!isEnd) {
                throw new BusinessException(filename + ":中的node没有定义结束节点为空请检查模版。");
            }
            if (nodeModeMap.size() == 0) {
                throw new BusinessException(filename + ":中的node没有定义节点为空请检查模版。");
            }
            ruleModel.setNodeModelMap(nodeModeMap);

            //sequenceFlow 节点集合
            Iterator seqf = root.elementIterator("sequenceFlow");
            SequenceFlowModel sequenceFlowModel = null;
            Map<String, SequenceFlowModel> sequenceFlowModeMap = new LinkedHashMap<String, SequenceFlowModel>();

            String seqid = null;
            String seqName = null;
            while (seqf.hasNext()) {
                sequenceFlowModel = new SequenceFlowModel();
                Element seqE = (Element) seqf.next();
                seqid = seqE.attributeValue("id");
                seqName = seqE.attributeValue("name");
                if (StringUtils.isBlank(seqid)) {
                    throw new BusinessException(filename + ":中的sequenceFlow id为空请检查模版。");
                }
                if (StringUtils.isBlank(seqName)) {
                    throw new BusinessException(filename + ":中的sequenceFlow name为空请检查模版。");
                }
                sequenceFlowModel.setId(seqid);
                sequenceFlowModel.setName(seqName);
                sequenceFlowModel.setDescription(seqE.attributeValue("description"));
                String[] arr = seqid.split("_");
                String fromNodeID = arr[0];
                String nextNodeID = arr[1];
                if (nodeModeMap.get(fromNodeID) == null) {
                    throw new BusinessException(filename + ":中的划线的开始节点不存在，请检查模版。" + seqid);
                }
                if (nodeModeMap.get(nextNodeID) == null) {
                    throw new BusinessException(filename + ":中的划线的结束节点不存在，请检查模版。" + seqid);
                }
                sequenceFlowModel.setFromNode(nodeModeMap.get(fromNodeID));
                sequenceFlowModel.setNextNode(nodeModeMap.get(nextNodeID));
                if (sequenceFlowModeMap.put(seqid, sequenceFlowModel) != null) {
                    throw new BusinessException(filename + ":中的划线重复，请检查模版。" + seqid);
                }
                sequenceFlowModel.setNeedNodes(StringUtils.split(seqE.attributeValue("needNodes"), ","));
            }
            if (sequenceFlowModeMap.size() == 0) {
                throw new BusinessException(filename + ":中的sequenceFlow没有定义，请检查模版。");
            }
            ruleModel.setSequenceFlowModelMap(sequenceFlowModeMap);

            //parentworkflow 节点
            Element pwflowE = root.element("parentworkflow");
            if (pwflowE != null) {
                ruleModel.setPnodename(pwflowE.attributeValue("name"));
                ruleModel.setPnodename("parentnodename");
            }
        } catch (DocumentException e) {
            e.printStackTrace();
            throw e;
        }

        clock.stop();
        log.debug("解析流程文件：" + file.getAbsolutePath() + " 耗时:" + clock.getTime() + "毫秒。");
        return ruleModel;
    }
}
