package org.hanuna.gitalk.printmodel.layout;

import org.hanuna.gitalk.common.compressedlist.generator.AbstractGenerator;
import org.hanuna.gitalk.graph.Graph;
import org.hanuna.gitalk.graph.elements.Edge;
import org.hanuna.gitalk.graph.elements.GraphElement;
import org.hanuna.gitalk.graph.elements.Node;
import org.hanuna.gitalk.graph.elements.NodeRow;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/**
 * @author erokhins
 */
class LayoutRowGenerator extends AbstractGenerator<MutableLayoutRow, LayoutRow> {
    private final Graph graph;

    public LayoutRowGenerator(@NotNull Graph graph) {
        this.graph = graph;
    }

    @NotNull
    @Override
    protected MutableLayoutRow createMutable(@NotNull LayoutRow cellRow) {
        return new MutableLayoutRow(cellRow);
    }

    @NotNull
    private List<Edge> orderAddEdges(@NotNull List<Edge> edges) {
        if (edges.size() <= 1) {
            return edges;
        } else {
            List<Edge> sortEdges = new ArrayList<Edge>(edges);
            Collections.sort(sortEdges, new Comparator<Edge>() {
                @Override
                public int compare(Edge o1, Edge o2) {
                    if (o1.getDownNode().getRowIndex() > o2.getDownNode().getRowIndex()) {
                        return -1;
                    } else {
                        return 1;
                    }
                }
            });
            return sortEdges;
        }
    }

    @NotNull
    @Override
    protected MutableLayoutRow oneStep(@NotNull MutableLayoutRow row) {
        int newRowIndex = row.getGraphNodeRow().getRowIndex() + 1;
        if (newRowIndex == graph.getNodeRows().size()) {
            throw new NoSuchElementException();
        }
        List<GraphElement> layoutRow = row.getModifiableOrderedGraphElements();
        for (ListIterator<GraphElement> iterator = layoutRow.listIterator(); iterator.hasNext(); ) {
            GraphElement element = iterator.next();
            Node node = element.getNode();
            if (node != null) {
                List<Edge> edges = node.getDownEdges();
                if (edges.size() == 0) {
                    iterator.remove();
                } else {
                    iterator.remove();
                    for (Edge edge : orderAddEdges(edges)) {
                        Node downNode = edge.getDownNode();
                        if (downNode.getRowIndex() == newRowIndex) {
                            if (downNode.getBranch() == edge.getBranch()) {
                                iterator.add(downNode);
                            }
                        } else {
                            iterator.add(edge);
                        }
                    }
                }
            } else {
                Edge edge = element.getEdge();
                if (edge == null) {
                    throw new IllegalStateException("unexpected element class");
                }
                if (edge.getDownNode().getRowIndex() == newRowIndex) {
                    if (edge.getBranch() == edge.getDownNode().getBranch()) {
                        iterator.set(edge.getDownNode());
                    } else {
                        iterator.remove();
                    }
                }
            }
        }
        NodeRow nextGraphRow = graph.getNodeRows().get(newRowIndex);
        for (Node node : nextGraphRow.getNodes()) {
            if (node.getUpEdges().isEmpty()) {
                layoutRow.add(node);
            }
        }
        row.setNodeRow(nextGraphRow);
        return row;
    }
}

@@ -1811,24 +1811,84 @@
 Elements();%0A
+        Set%3CNode%3E addedNodeInNextRow = new HashSet%3CNode%3E();%0A
         for 
@@ -2529,47 +2529,45 @@
 if (
-downNode.getBranch() == edge.getBranch(
+!addedNodeInNextRow.contains(downNode
 )) %7B
@@ -2619,24 +2619,90 @@
 (downNode);%0A
+                                addedNodeInNextRow.add(downNode);%0A
             
@@ -3168,28 +3168,37 @@
 if (
-edge.getBranch() == 
+!addedNodeInNextRow.contains(
 edge
@@ -3215,19 +3215,8 @@
 de()
-.getBranch(
 )) %7B
@@ -3274,16 +3274,84 @@
 ode());%0A
+                        addedNodeInNextRow.add(edge.getDownNode());%0A
         

fix depend of Branches in Graph