package cn.stylefeng.workflow.instance.modular.mobile.sort;

import cn.stylefeng.workflow.api.entity.design.Node;
import cn.stylefeng.workflow.api.entity.design.NodeEdge;

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

public class WorkflowSorter {

    public static List<Node> sortNodes(List<Node> nodes, List<NodeEdge> edges) {

        Map<Long, Node> nodeMap = nodes.stream().collect(Collectors.toMap(Node::getNodeId, node -> node));

        Map<Long, List<Long>> adjacencyList = new HashMap<>();

        Map<Long, Integer> inDegree = new HashMap<>();

        for (Node node : nodes) {
            adjacencyList.put(node.getNodeId(), new ArrayList<>());
            inDegree.put(node.getNodeId(), 0);
        }

        for (NodeEdge edge : edges) {
            Long source = edge.getSourceNodeId();
            Long target = edge.getTargetNodeId();
            adjacencyList.get(source).add(target);
            inDegree.put(target, inDegree.get(target) + 1);
        }

        Queue<Long> queue = new LinkedList<>();

        for (Map.Entry<Long, Integer> entry : inDegree.entrySet()) {
            if (entry.getValue() == 0) {
                queue.add(entry.getKey());
            }
        }

        List<Node> sortedNodes = new ArrayList<>();

        while (!queue.isEmpty()) {
            Long nodeId = queue.poll();
            sortedNodes.add(nodeMap.get(nodeId));

            for (Long neighbor : adjacencyList.get(nodeId)) {

                inDegree.put(neighbor, inDegree.get(neighbor) - 1);

                if (inDegree.get(neighbor) == 0) {
                    queue.add(neighbor);
                }
            }
        }

        if (sortedNodes.size() != nodes.size()) {
            throw new IllegalStateException("流程中存在循环");
        }

        return sortedNodes;
    }

}
