///usr/bin/env jbang "$0" "$@" ; exit $?
//JAVA 17+
//DEPS guru.nidi:graphviz-java:0.18.1
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import guru.nidi.graphviz.attribute.*;
import guru.nidi.graphviz.engine.Engine;
import guru.nidi.graphviz.engine.Format;
import guru.nidi.graphviz.engine.Graphviz;
import guru.nidi.graphviz.model.*;
import guru.nidi.graphviz.parse.Parser;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Pattern;

import static guru.nidi.graphviz.model.Factory.*;

public class ReactorGraph {
    private static final LinkedHashMap<String, Pattern> CLUSTER_PATTERNS = new LinkedHashMap<>();
    static {
        CLUSTER_PATTERNS.put("JLine", Pattern.compile("^org\\.jline:.*"));
        CLUSTER_PATTERNS.put("Maven 4 API", Pattern.compile("^org\\.apache\\.maven:maven-api-(?!impl).*"));
        CLUSTER_PATTERNS.put("Maven Resolver 2", Pattern.compile("^org\\.apache\\.maven\\.resolver:.*"));
        CLUSTER_PATTERNS.put("Maven 4 Implementation", Pattern.compile("^org\\.apache\\.maven:maven-(support|impl|di|core|cli|xml|jline|logging|executor|testing):.*"));
        CLUSTER_PATTERNS.put("Maven 3 Compatibility", Pattern.compile("^org\\.apache\\.maven:maven-(artifact|builder-support|compat|embedder|model|model-builder|plugin-api|repository-metadata|resolver-provider|settings|settings-builder|toolchain-builder|toolchain-model):.*"));
        CLUSTER_PATTERNS.put("Sisu", Pattern.compile("(^org\\.eclipse\\.sisu:.*)|(.*:guice:.*)|(.*:javax.inject:.*)|(.*:javax.annotation-api:.*)|(.*:aopalliance:.*)"));
        CLUSTER_PATTERNS.put("Plexus", Pattern.compile("^org\\.codehaus\\.plexus:.*"));
        CLUSTER_PATTERNS.put("XML Parsing", Pattern.compile("(.*:woodstox-core:.*)|(.*:stax2-api:.*)"));
        CLUSTER_PATTERNS.put("Wagon", Pattern.compile("^org\\.apache\\.maven\\.wagon:.*"));
        CLUSTER_PATTERNS.put("SLF4j", Pattern.compile("^org\\.slf4j:.*"));
        CLUSTER_PATTERNS.put("Commons", Pattern.compile("^commons-cli:.*"));
        CLUSTER_PATTERNS.put("Testing", Pattern.compile("^.*:(mockito-core|junit-jupiter-api):.*"));
    }
    private static final Pattern HIDDEN_NODES = Pattern.compile(".*:(maven-docgen|roaster-api|roaster-jdt|velocity-engine-core|commons-lang3|asm|logback-classic|slf4j-simple|domtrip-core|domtrip-maven):.*");

    public static void main(String[] args) {
        try {
            // Parse DOT file generated by org.fusesource.mvnplugins:maven-graph-plugin:reactor
            MutableGraph originalGraph = new Parser().read(new File("target/graph/reactor-graph.dot"));

            // Create final graph
            MutableGraph clusteredGraph = mutGraph("G").setDirected(true);
            clusteredGraph.graphAttrs().add(GraphAttr.COMPOUND);
            clusteredGraph.graphAttrs().add(Label.of("Reactor Graph"));
            clusteredGraph.nodeAttrs().add("fontname", "Arial");

            // Create clusters
            Map<String, MutableGraph> clusters = new HashMap<>();
            for (String clusterName : CLUSTER_PATTERNS.keySet()) {
                String key = "cluster_" + clusterName.replaceAll("\\s+", "");
                MutableGraph cluster = mutGraph(key).setDirected(true);
                cluster.graphAttrs().add(Label.of(clusterName));
                clusters.put(clusterName, cluster);
                clusteredGraph.add(cluster);
            }

            // Map to store new nodes by node name
            Map<String, MutableNode> nodeMap = new HashMap<>();
            Map<String, String> nodeToCluster = new HashMap<>();
            Map<String, String> newNames = new HashMap<>();

            // First pass: Create nodes and organize them into clusters
            for (MutableNode originalNode : originalGraph.nodes()) {
                String oldNodeName = originalNode.name().toString();
                if (HIDDEN_NODES.matcher(oldNodeName).matches()) {
                    continue;
                }
                String nodeName = oldNodeName;
                if (originalNode.get("label") instanceof Label l) {
                    nodeName = l.value();
                    // fix "guice\njar:classes" label caused by classifier
                    int i = nodeName.indexOf('\\');
                    if (i > 0) {
                        nodeName = nodeName.substring(0, i);
                    }
                }
                MutableNode newNode = mutNode(nodeName);
                nodeMap.put(nodeName, newNode);
                newNames.put(oldNodeName, nodeName);

                boolean added = false;
                for (Map.Entry<String, Pattern> entry : CLUSTER_PATTERNS.entrySet()) {
                    if (entry.getValue().matcher(oldNodeName).matches()) {
                        clusters.get(entry.getKey()).add(newNode);
                        nodeToCluster.put(nodeName, entry.getKey());
                        added = true;
                        break;
                    }
                }

                if (!added) {
                    clusteredGraph.add(newNode);
                }
            }

            // Second pass: Add links to the clustered graph
            Map<String, MutableNode> substitutes = new HashMap<>();
            Set<Pair> existingLinks = new HashSet<>();
            for (MutableNode node : originalGraph.nodes()) {
                for (Link link : node.links()) {
                    String sourceName = newNames.get(link.from().name().toString());
                    String targetName = newNames.get(link.to().name().toString());
                    String sourceCluster = nodeToCluster.get(sourceName);
                    String targetCluster = nodeToCluster.get(targetName);
                    MutableNode sourceNode = nodeMap.get(sourceName);
                    MutableNode targetNode = nodeMap.get(targetName);
                    if (sourceNode != null && targetNode != null ) {
                        if (!Objects.equals(sourceCluster, targetCluster)) {
                            // Inter-cluster link
                            if (sourceCluster != null) {
                                sourceName = "cluster_" + sourceCluster.replaceAll("\\s+", "");
                            }
                            if (targetCluster != null) {
                                targetName = "cluster_" + targetCluster.replaceAll("\\s+", "");
                            }
                            sourceNode = substitutes.computeIfAbsent(sourceName, n -> createNode(n, clusteredGraph));
                            targetNode = substitutes.computeIfAbsent(targetName, n -> createNode(n, clusteredGraph));
                        }
                        if (existingLinks.add(new Pair(sourceName, targetName))) {
                            sourceNode.addLink(targetNode);
                        }
                    }
                }
            }

            // Write intermediary graph to DOT file
            String dotContent = Graphviz.fromGraph(clusteredGraph).render(Format.DOT).toString();
            Files.write(Paths.get("target/graph/intermediary_graph.dot"), dotContent.getBytes());
            System.out.println("Intermediary graph written to intermediary_graph.dot");

            // Render graph to SVG
            Graphviz.fromGraph(clusteredGraph)
                    .engine(Engine.FDP)
                    .render(Format.SVG).toFile(new File("target/graph/intermediary_graph.svg"));
            System.out.println("Final graph rendered to intermediary_graph.svg");

            // Generate and render the high-level graph
            MutableGraph highLevelGraph = generateHighLevelGraph(clusteredGraph, clusters, nodeToCluster, nodeMap);

            // Write high-level graph to DOT file
            String highLevelDotContent = Graphviz.fromGraph(highLevelGraph).render(Format.DOT).toString();
            Files.write(Paths.get("target/graph/high_level_graph.dot"), highLevelDotContent.getBytes());
            System.out.println("High-level graph written to high_level_graph.dot");

            // Render high-level graph to SVG
            Graphviz.fromGraph(highLevelGraph)
                    .engine(Engine.DOT)
                    .render(Format.SVG).toFile(new File("target/site/images/maven-deps.svg"));
            System.out.println("High-level graph rendered to maven-deps.svg");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static MutableGraph generateHighLevelGraph(MutableGraph clusteredGraph, Map<String, MutableGraph> clusters,
                                                       Map<String, String> nodeToCluster, Map<String, MutableNode> nodeMap) {
        MutableGraph highLevelGraph = mutGraph("HighLevelGraph").setDirected(true);
        highLevelGraph.graphAttrs().add(GraphAttr.COMPOUND);
        highLevelGraph.graphAttrs().add(Label.of("High-Level Reactor Graph"));
        highLevelGraph.nodeAttrs().add("fontname", "Arial");

        Map<String, MutableNode> highLevelNodes = new HashMap<>();

        // Create nodes for each cluster
        for (Map.Entry<String, MutableGraph> entry : clusters.entrySet()) {
            String key = entry.getKey();
            String clusterName = key.replaceAll("\\s+", "");
            MutableGraph cluster = entry.getValue();

            String headerColor = clusterName.startsWith("Maven") ? "black" : "#808080";  // #808080 is a middle gray
            String prefix;
            switch (clusterName) {
                case "Maven4API": prefix = "../api/"; break;
                case "Maven4Implementation": prefix = "../impl/"; break;
                case "Maven3Compatibility": prefix = "../compat/"; break;
                case "MavenResolver2": prefix = "https://maven.apache.org/resolver/"; break;
                default: prefix = null;
            }

            StringBuilder labelBuilder = new StringBuilder();
            labelBuilder.append("<table border='0' cellborder='0' cellspacing='0'>")
                    .append("<th border='1'><td cellpadding='5' bgcolor='")
                    .append(headerColor)
                    .append("'><font color='white'><b>&nbsp;")
                    .append(key)
                    .append("&nbsp;</b></font></td></th>");
            cluster.nodes().stream().map(MutableNode::name).map(Label::toString).sorted()
                    .forEach(nodeName -> {
                        labelBuilder.append("<tr><td align='left'");
                        if (prefix != null) {
                            labelBuilder.append(" href='").append(prefix).append(nodeName)
                                    .append("' title='").append(nodeName).append("' target='_parent'");
                        }
                        labelBuilder.append(">").append(nodeName).append("</td></tr>");
                    });
            labelBuilder.append("</table>");

            MutableNode clusterNode = mutNode(clusterName).add(Label.html(labelBuilder.toString()))
                    .add("shape", "rectangle");
            highLevelNodes.put(clusterName, clusterNode);
            highLevelGraph.add(clusterNode);
        }

        // Add individual nodes for unclustered nodes
        for (MutableNode node : clusteredGraph.nodes()) {
            String nodeName = node.name().toString();
            if (!nodeToCluster.containsKey(nodeName) && !nodeName.startsWith("cluster_")) {
                throw new IllegalStateException("All nodes should be in a cluster: " + node.name());
            }
        }

        // Add edges
        Set<Pair> existingLinks = new HashSet<>();
        for (MutableNode node : clusteredGraph.nodes()) {
            String sourceName = node.name().toString().replace("cluster_", "");
            String sourceCluster = nodeToCluster.getOrDefault(sourceName, sourceName);

            for (Link link : node.links()) {
                String targetName = link.to().name().toString().replace("cluster_", "");
                String targetCluster = nodeToCluster.getOrDefault(targetName, targetName);

                Pair linkPair = new Pair(sourceCluster, targetCluster);
                if (existingLinks.add(linkPair)) {
                    MutableNode sourceNode = highLevelNodes.get(sourceCluster);
                    MutableNode targetNode = highLevelNodes.get(targetCluster);
                    if (sourceNode != null && targetNode != null && sourceNode != targetNode) {
                        sourceNode.addLink(targetNode);
                    }
                }
            }
        }

        // force top group
        MutableGraph topGroup = mutGraph("top")
                .setDirected(true)
                .graphAttrs().add(Rank.inSubgraph(Rank.RankType.SAME))
                .add(
                        mutNode("MavenResolver2"),
                        mutNode("Maven4API"),
                        mutNode("Maven4Implementation")
                );
        highLevelGraph.add(topGroup);

        return highLevelGraph;
    }

    private static MutableNode createNode(String n, MutableGraph clusteredGraph) {
        MutableNode t = mutNode(n);
        clusteredGraph.add(t);
        return t;
    }

    record Pair(String from, String to) {};
}