package io.github.programminglife2016.pl1_2016.collapser;

import io.github.programminglife2016.pl1_2016.parser.nodes.Node;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Created by ravishivam on 16-5-16.
 *
 */
public class BubbleCollapser {

    List<Bubble> bubbles;

    public BubbleCollapser(List<Bubble> bubbles){
        this.bubbles = bubbles;
    }

    public void collapseBubbles(){
        for (Bubble bubble : bubbles)
            bubble.getContainer().addAll(breadth(bubble));
        addLinks(bubbles);
    }

    private List<Node> breadth(Bubble bubble) {
        int startId =  bubble.getStartNode().getId();
        int endId =  bubble.getEndNode().getId();
        Queue<Node> q = new ConcurrentLinkedQueue<>();
        q.add(bubble.getStartNode());
        List<Node> visited = new ArrayList<>();
        while (!q.isEmpty()) {
            Node n = q.poll();
            for (Node v : n.getLinks()) {
                if (visited.contains(v) || v.getId() == startId || v.getId() == endId)
                    continue;
                v.setContainerId(bubble.getId());
                q.add(v);
                visited.add(v);
            }
        }
        return visited;
    }

    private void addLinks(List<Bubble> bubbles){
        for (Bubble bubble : bubbles){
            addBackLinks(bubble);
            addForwardLinks(bubble);
        }
    }

    private void addBackLinks(Bubble bubble){
        Optional<Bubble> container;
        for(Node node: bubble.getStartNode().getBackLinks()) {
            container = bubbles.stream().filter(x -> x.getId() == node.getContainerId()).findFirst();
            if (container.isPresent())
                bubble.getBackLinks().add(container.get());
            else
                bubble.getBackLinks().add(node);
        }
        System.out.println("Id: " + bubble.getId() + " BackLinks:" + bubble.getBackLinks().size());
    }

    private void addForwardLinks(Bubble bubble){
        Optional<Bubble> container;
        for(Node node: bubble.getEndNode().getLinks()) {
            container = bubbles.stream().filter(x -> x.getId() == node.getContainerId()).findFirst();
            if (container.isPresent())
                bubble.getLinks().add(container.get());
            else
                bubble.getLinks().add(node);
        }
        System.out.println("Id: " + bubble.getId() + " ForwardLinks:" + bubble.getBackLinks().size());
    }
}

@@ -139,91 +139,9 @@
 til.
-ArrayList;%0Aimport java.util.List;%0Aimport java.util.Optional;%0Aimport java.util.Queue
+*
 ;%0Aim
@@ -188,16 +188,52 @@
 edQueue;
+%0Aimport java.util.stream.Collectors;
 %0A%0A/**%0A *
@@ -1491,32 +1491,34 @@
 e)%7B%0A        
-Op
+Collec
 tion
-al
 %3CBubble%3E con
@@ -1633,32 +1633,34 @@
 m().filter(x -%3E 
+//
 x.getId() == nod
@@ -1673,37 +1673,132 @@
 ontainerId()
-).findFirs
+ &&%0A                    x.getEndNode().getId() == bubble.getStartNode().getId()).collect(Collectors.toSe
 t()
+)
 ;%0A          
@@ -1809,35 +1809,34 @@
  (container.
-isPresent()
+size() %3E 0
 )%0A          
@@ -1858,32 +1858,35 @@
 tBackLinks().add
+All
 (container.get()
@@ -1871,38 +1871,32 @@
 addAll(container
-.get()
 );%0A            e
@@ -2019,32 +2019,46 @@
 %22 BackLinks:%22 + 
+linksToString(
 bubble.getBackLi
@@ -2054,38 +2054,32 @@
 e.getBackLinks()
-.size(
 ));%0A    %7D%0A%0A    p
@@ -2134,16 +2134,18 @@
     
-Op
+Collec
 tion
-al
 %3CBub
@@ -2270,16 +2270,18 @@
 er(x -%3E 
+//
 x.getId(
@@ -2310,21 +2310,116 @@
 Id()
-).findFirs
+ &&%0A                    x.getStartNode().getId() == bubble.getEndNode().getId()).collect(Collectors.toSe
 t()
+)
 ;%0A  
@@ -2446,19 +2446,18 @@
 ner.
-isPresent()
+size() %3E 0
 )%0A  
@@ -2491,16 +2491,19 @@
 ks().add
+All
 (contain
@@ -2508,14 +2508,8 @@
 iner
-.get()
 );%0A 
@@ -2655,37 +2655,325 @@
 %22 + 
-bubble.getBackLinks().size())
+linksToString(bubble.getLinks()));%0A    %7D%0A%0A    /**%0A     * Temporary method to view changes in links%0A     * @param links%0A     * @return%0A     */%0A    private String linksToString(Collection%3CNode%3E links)%7B%0A        String result = %22%22;%0A        for (Node n: links)%0A            result += n.getId() + %22, %22;%0A        return result
 ;%0A  

Add links in multi-level bubble structure