package uk.ac.ebi.quickgo.ontology.traversal;

import uk.ac.ebi.quickgo.ontology.model.AncestorGraph;
import uk.ac.ebi.quickgo.ontology.model.OntologyRelationType;
import uk.ac.ebi.quickgo.ontology.model.OntologyRelationship;

import java.util.Deque;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
 * Encapsulates the calculation of a edges for a single vertex, and the creation of further instances for vertexes
 * attached to those edges.
 * @author Tony Wardell
 * Date: 19/06/2017
 * Time: 10:11
 * Created with IntelliJ IDEA.
 */
class SubGraphCalculator {

    static Trampoline<AncestorGraph> createTrampoline(Deque<String> targetVertices, Set<String> stopNodes,
            OntologyRelationType[] targetRelations, AncestorGraph ancestorGraph, OntologyGraph ontologyGraph) {

        String target = targetVertices.pollFirst();

        if(Objects.nonNull(target)){
            ancestorGraph.vertices.add(target);
        }

        //if target is null, or is a stop node, and we don't have any more to process then don't create any more
        if (Objects.isNull(target) || stopNodes.contains(target) && targetVertices.isEmpty()){
            return new Trampoline<AncestorGraph>(){
                public AncestorGraph getValue() { return ancestorGraph; }
            };
        }

        try {
            Set<OntologyRelationship> parents = ontologyGraph.parents(target, targetRelations);
            ancestorGraph.edges.addAll(parents);
            addParentsToWorkQueue(targetVertices, parents);

        } catch (Exception e) {
            return new Trampoline<AncestorGraph>(){
                public AncestorGraph getValue() { return ancestorGraph; }
            };
        }

        return new Trampoline<AncestorGraph>() {
            public Optional<Trampoline<AncestorGraph>> nextTrampoline() {
                return Optional.of(createTrampoline(targetVertices, stopNodes, targetRelations, ancestorGraph, ontologyGraph));
            }
        };
    }

    private static void addParentsToWorkQueue(Deque<String> targetVertices, Set<OntologyRelationship> parents) {
        parents.stream()
               .map(p -> p.parent)
               .forEach(targetVertices::addLast);
    }
}

@@ -872,16 +872,17 @@
       if
+ 
 (Objects
@@ -898,17 +898,19 @@
 target))
-%7B
+ %7B%0A
 %0A       
@@ -918,388 +918,294 @@
     
-ancestorGraph.vertices.add(target);%0A        %7D%0A%0A        //if target is null, or is a stop node, and we don't have any more to process then don't create any more%0A        if (Objects.isNull(target) %7C%7C stopNodes.contains(target) && targetVertices.isEmpty())%7B%0A            return new Trampoline%3CAncestorGraph%3E()%7B%0A                public AncestorGraph getValue() %7B return ancestorGraph; %7D
+//Process this node if it hasn't already been considered.%0A            if (!ancestorGraph.vertices.contains(target)) %7B%0A                ancestorGraph.vertices.add(target);%0A%0A                //if target is not a stop node look for parents%0A                if (!stopNodes.contains(target)) %7B%0A
 %0A   
@@ -1209,35 +1209,32 @@
             
-%7D;%0A
         
 %7D%0A%0A        t
@@ -1213,34 +1213,37 @@
                 
-%7D%0A
+try %7B
 %0A        try %7B%0A 
@@ -1227,38 +1227,36 @@
   try %7B%0A        
-try %7B%0A
+    
             Set%3C
@@ -1331,24 +1331,36 @@
 Relations);%0A
+            
             
@@ -1408,16 +1408,28 @@
         
+            
 addParen
@@ -1465,24 +1465,36 @@
  parents);%0A%0A
+            
         %7D ca
@@ -1509,24 +1509,174 @@
 eption e) %7B%0A
+                        //continue processing.%0A                    %7D%0A                %7D%0A            %7D%0A%0A            if(!targetVertices.isEmpty()) %7B%0A    
             
@@ -1713,18 +1713,23 @@
 Graph%3E()
+ 
 %7B%0A
+    
         
@@ -1747,73 +1747,494 @@
 lic 
-AncestorGraph getValue() %7B return ancestorGraph; %7D%0A            %7D;
+Optional%3CTrampoline%3CAncestorGraph%3E%3E nextTrampoline() %7B%0A                        return Optional.of(createTrampoline(targetVertices,%0A                                                            stopNodes,%0A                                                            targetRelations,%0A                                                            ancestorGraph,%0A                                                            ontologyGraph));%0A                    %7D%0A                %7D;%0A            %7D%0A
 %0A   
@@ -2232,33 +2232,32 @@
    %7D%0A%0A        %7D%0A
-%0A
         return n
@@ -2312,202 +2312,56 @@
 lic 
-Optional%3CTrampoline%3CAncestorGraph%3E%3E nextTrampoline() %7B%0A                return Optional.of(createTrampoline(targetVertices, stopNodes, targetRelations, ancestorGraph, ontologyGraph));%0A           
+AncestorGraph getValue() %7B return ancestorGraph;
  %7D%0A 
@@ -2366,24 +2366,25 @@
 %0A        %7D;%0A
+%0A
     %7D%0A%0A    p

Simplify calculator logic.