package com.ho.flow.util;



import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.ho.flow.vo.XmlBean;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.StringReader;
import java.util.*;
import java.util.stream.Collectors;

public class XmlToJsonUtil {

    public static final String ALL_USER = "_allUser";

    public static final String FIRST_USER = "_firstUser";

    public static final String PRE_BACK = "_preBack";

    public static final String AS_NODE = "_asNode";

    public static Map<String,String> getTaskUsers(String xmlStr){
        Map<String,String> result = new HashMap<String,String>();
        JSONObject jsonObject = xmlToJson(xmlStr);
        JSONObject process = null;
        if ( jsonObject.containsKey("process") ){
            process = JSONObject.from(jsonObject.get("process"));
        }
        JSONObject content = null;
        if ( process.containsKey("content") ) {
            content = JSONObject.from(process.get("content"));
        }
        JSONArray userTask = null;
        if ( content.containsKey("userTask") ) {
            userTask = JSONArray.from(content.get("userTask"));
        }
        List<Map<String, String>> collect = null;
        if ( userTask != null ) {
            collect = userTask.stream().map( task -> {
                Map<String, String> map = new HashMap<String, String>();
                JSONObject from = JSONObject.from(task);
                if( from.containsKey("candidateUsers") ){
                    map.put("candidateUsers", from.get("candidateUsers").toString());
                }
                if( from.containsKey("candidateGroups") ){
                    map.put("candidateGroups",from.get("candidateGroups").toString());
                }
                return map;
            }).collect(Collectors.toList());
        }
        if( collect != null && collect.size() > 0 ){
            result = collect.get(0);
        }
        return result;
    }

    public static Map<String,Map<String,String>> getAllTaskUsers(String xmlStr){
        Map<String,Map<String,String>> result = new HashMap<String,Map<String,String>>(0);
        Map<String,String> dataMap = new HashMap<String,String>();
        JSONObject jsonObject = xmlToJson(xmlStr);
        JSONObject process = null;
        if ( jsonObject.containsKey("process") ){
            process = JSONObject.from(jsonObject.get("process"));
        }
        JSONObject content = null;
        if ( process.containsKey("content") ) {
            content = JSONObject.from(process.get("content"));
        }
        JSONArray userTask = null;
        if ( content.containsKey("userTask") ) {
            userTask = JSONArray.from(content.get("userTask"));
        }
        List<Map<String, String>> collect = null;
        if ( userTask != null ) {
            collect = userTask.stream().map( task -> {
                Map<String, String> map = new HashMap<String, String>();
                JSONObject from = JSONObject.from(task);
                if( from.containsKey("id") ){
                    map.put("id", from.getString("id"));
                }
                if( from.containsKey("candidateUsers") ){
                    map.put("candidateUsers", from.getString("candidateUsers"));
                }
                if( from.containsKey("candidateGroups") ){
                    map.put("candidateGroups",from.getString("candidateGroups"));
                }
                return map;
            }).collect(Collectors.toList());
        }
        for (Map<String, String> data : collect) {
            result.put(data.get("id"),data);
        }
        return result;
    }

    /**
     * 获取前面所有的用户节点
     * @param xml   xml字符串
     * @param key   当前节点的id
     * @return
     */
    public static LinkedList<String> getPreTaskNodes(String xml, String key){
        LinkedList<String> nodeKeys = new LinkedList<>();
        JSONObject jsonObject = xmlToJson(xml);
        // 取process节点
        JSONObject process = jsonObject.getJSONObject("process");
        // 取content节点
        JSONObject content = process.getJSONObject("content");

        // 取指向箭头
        JSONArray sequenceFlows = content.getJSONArray("sequenceFlow");
        // 取网关
        JSONArray exclusiveGateway = content.getJSONArray("exclusiveGateway");
        // 网关id map
        Map<String,String> gateWayMap = getMapFromJsonArray(exclusiveGateway);

        // 取用户节点
        JSONArray userTask = content.getJSONArray("userTask");
        // 用户节点id map
        Map<String,String> taskMap = getMapFromJsonArray(userTask);

        // 取开始节点
        JSONObject startEvent = content.getJSONObject("startEvent");
        int index = 1;
        for (Object o : sequenceFlows) {
            JSONObject sequenceFlow = JSONObject.from(o);
            // 来
            String sourceRef = sequenceFlow.getString("sourceRef");
            if( taskMap.containsKey(sourceRef) ){
                System.out.println("sourceRef = " + sourceRef + " -> index = " + index);
                nodeKeys.add(sourceRef);
                index++;
            }
            if( sourceRef.equals(key) ){
                break;
            }
        }
        return nodeKeys;
    }

    private static Map<String,String> getMapFromJsonArray(JSONArray jsonArray) {
        Map<String,String> result = new HashMap<>();
        if (jsonArray != null) {
            for (Object o : jsonArray) {
                JSONObject task = JSONObject.from(o);
                String id = task.getString("id");
                result.put(id, id);
            }
        }
        return result;
    }

    /**
     * 获取当前节点之前和之后的节点是否是网关,开始或结束节点
     * @param xml
     */
    public static List<XmlBean> getOtherNodeType(String xml){
        JSONObject jsonObject = getProcess(xml);

        // 流程id
        String id = "";
        if( jsonObject.containsKey("id") ){
            id = jsonObject.getString("id");
        }

        JSONObject content = null;
        if( jsonObject.containsKey("content") ){
            content = jsonObject.getJSONObject("content");
        }

        if( content == null ){
            System.out.println("content为空,直接跳出");
            return null;
        }

        // 开始节点id
        String startId = "";
        if( content.containsKey("startEvent") ){
            startId = content.getJSONObject("startEvent").getString("id");
        }
        //System.out.println("startId = " + startId);

        // 结束节点id
        String endId = "";
        if( content.containsKey("endEvent") ){
            endId = content.getJSONObject("endEvent").getString("id");
        }
        //System.out.println("endId = " + endId);

        // 取所有网关
        JSONArray exclusiveGateway = new JSONArray();
        if( content.containsKey("exclusiveGateway") ){
            exclusiveGateway = content.getJSONArray("exclusiveGateway");
        }

        Map<String,String> gateways = new HashMap<String,String>(0);

        for (Object o : exclusiveGateway) {
            JSONObject json = JSONObject.from(o);
            gateways.put(getNodeValueFromObject(json,"id"),"");
        }

        // 指向箭头
        JSONArray sequenceFlow = null;
        if( content.containsKey("sequenceFlow") ){
            sequenceFlow = content.getJSONArray("sequenceFlow");
        }
        Map<String,Map<String,String>> flowMap = new HashMap<String,Map<String,String>>(0);
        Map<String,String> flow = null;

        for (Object o : sequenceFlow) {
            flow = new HashMap<String,String>(0);
            JSONObject json = JSONObject.from(o);
            // 来
            String sourceRef = getNodeValueFromObject(json,"sourceRef");
            // 去
            String targetRef = getNodeValueFromObject(json,"targetRef");
            flow.put("sourceRef",sourceRef);
            flow.put("targetRef",targetRef);
            flowMap.put(json.getString("id"),flow);
        }

        // 用户节点
        JSONArray userTask = null;
        if( content.containsKey("userTask") ){
            userTask = content.getJSONArray("userTask");
        }

        List<XmlBean> beans = new ArrayList<XmlBean>(0);
        XmlBean bean = null;

        if(userTask != null){
            for (Object o : userTask) {
                bean = new XmlBean();
                JSONObject json = JSONObject.from(o);
                bean.setNodeKey(getNodeValueFromObject(json,"id"));
                if( json.containsKey("content") ){
                    JSONObject userTaskContent = json.getJSONObject("content");
                    // 从哪里来
                    String incoming = getNodeValueFromObject(userTaskContent, "incoming");
                    // 到哪里去
                    String outgoing = getNodeValueFromObject(userTaskContent, "outgoing");
                    if( flowMap.containsKey(incoming) ){
                        // 如果从这个箭头来,那么判断前一个节点是否是网关\开始
                        String sourceRef = getValueFromMap(flowMap, incoming, "sourceRef");
                        bean.setPreStart( sourceRef.equals(startId) );
                        bean.setPreGateway( gateways.containsKey(sourceRef) );
                        bean.setPreNodeKey(sourceRef);
                    }

                    if( flowMap.containsKey(outgoing) ){
                        // 如果到这个箭头去,那么判断后一个节点是否是网关\结束
                        String targetRef = getValueFromMap(flowMap, outgoing, "targetRef");
                        bean.setAfterGateway( gateways.containsKey(targetRef) );
                        bean.setAfterEnd( targetRef.equals(endId) );
                        bean.setAfterNodeKey(targetRef);
                    }
                }
                beans.add(bean);
            }
        }
        //beans.stream().forEach(System.out::println);
        return beans;
    }

    private static String getNodeValueFromObject(JSONObject json, String key){
        String value = "";
        if( json != null && json.containsKey(key) ){
            value = json.getString(key);
        }
        return value;
    }

    private static String getValueFromMap(Map<String, Map<String, String>> map, String key, String innerKey){
        String value = "";
        if( map != null && map.containsKey(key) ){
            Map<String,String> flow = map.get(key);
            if( flow != null && flow.containsKey(innerKey) ){
                value = flow.get(innerKey).toString();
            }
        }
        return value;
    }

    public static JSONObject getProcess(String xml) {
        JSONObject jsonObject = new JSONObject();
        if (StringUtil.isEmpty(xml)) {
            return jsonObject;
        }
        String xmlStr = replaceAllCahr(xml);
        try {
            jsonObject = xmlToJson(xmlStr);
            if (jsonObject.containsKey("process")) {
                jsonObject = JSONObject.from(jsonObject.get("process"));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return jsonObject;
    }

    /**
     * XML字符串转换JSON对象
     *
     * @param xmlStr XML字符串
     * @return JSON对象
     */
    public static JSONObject xmlToJson(String xmlStr) {
        JSONObject result = new JSONObject(1);
        SAXReader xmlReader = new SAXReader();
        try {
            Document document = xmlReader.read(new StringReader(xmlStr));
            Element element = document.getRootElement();
            return xmlToJson(element, result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * XML节点转换JSON对象
     *
     * @param element 节点
     * @param object  新的JSON存储
     * @return JSON对象
     */
    private static JSONObject xmlToJson(Element element, JSONObject object) {
        List<Element> elements = element.elements();
        for (Element child : elements) {
            Object value = object.get(child.getName());
            Object newValue;

            if (child.elements().size() > 0) {
                JSONObject jsonObject = xmlToJson(child, new JSONObject(1));
                if (!jsonObject.isEmpty()) {
                    newValue = jsonObject;
                } else {
                    newValue = child.getText();
                }
            } else {
                newValue = child.getText();
            }

            List<Attribute> attributes = child.attributes();
            if (!attributes.isEmpty()) {
                JSONObject attrJsonObject = new JSONObject();
                for (Attribute attribute : attributes) {
                    attrJsonObject.put(attribute.getName(), attribute.getText());
                    attrJsonObject.put("content", newValue);
                }
                newValue = attrJsonObject;
            }

            if (newValue != null) {
                if (value != null) {
                    if (value instanceof JSONArray) {
                        ((JSONArray) value).add(newValue);
                    } else {
                        JSONArray array = new JSONArray();
                        array.add(value);
                        array.add(newValue);
                        object.put(child.getName(), array);
                    }
                } else {
                    object.put(child.getName(), newValue);
                }
            }
        }
        return object;
    }

    public static String replaceAllCahr(String str) {
        return str.replaceAll("\r", "").replaceAll("\n", "")
                .replaceAll("\t", "");
    }

}
