package xyz.ignatz.flowchart;

import java.util.*;

import guru.nidi.graphviz.attribute.*;
import guru.nidi.graphviz.model.Graph;
import guru.nidi.graphviz.model.MutableNode;
import xyz.ignatz.flowchart.module.Block;
import xyz.ignatz.flowchart.module.INode;

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


public class Flowchart {
    Graph g;
    public Flowchart(String name, Block block) {
        Queue<INode> queue = new LinkedList<>();
        Map<INode, MutableNode> map = new HashMap<>();
        map.put(null, mutNode("END").add(Shape.BOX, Style.ROUNDED));
        queue.add(block.getStart());
        while (!queue.isEmpty()) {
            INode n = queue.poll();
            if (n == null) continue;
            map.put(n, mutNode(Label.html(n.html())));
            Collection<INode> ns = n.links().values();
            ns.removeAll(map.keySet());
            queue.addAll(ns);
        }
        map.forEach((i, n) -> {
            if (i == null) return;
            Map<String, INode> tps = i.links();
            n.add(tps.size() > 1 ? Shape.DIAMOND : Shape.BOX);
            tps.forEach((dsc, dst) -> n.addLink(to(map.get(dst)).with(Label.of(dsc))));
        });
        map.get(block.getStart()).add(Shape.BOX, Style.ROUNDED);
        g = mutGraph(name).setDirected(true)
                .graphAttrs().add(Rank.dir(Rank.RankDir.TOP_TO_BOTTOM))
                .graphAttrs().add(Font.config("Arial", 10))
                .add(new ArrayList<>(map.values())).toImmutable();
    }

    public Graph graph() {
        return g;
    }

    public String getName() {
        return g.name().value();
    }
}
