import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;

public class IdealIterator{
	
		class IdealIteratorTuple{
			Ideal ideal;
			SubsetIterator<Integer> iterator;
			
			 IdealIteratorTuple(Ideal ideal){
				 this.ideal = ideal;
				 this.iterator = ideal.exteriorChildrenSubsetIterator();
			 }
			 
			 IdealIteratorTuple(Ideal ideal, SubsetIterator<Integer> iterator){
				 this.ideal = ideal;
				 this.iterator = iterator;
			 }
		}
		
		Graph graph;
		Stack<IdealIteratorTuple> stk;
		HashSet<String> returnedIdeals;
		
		IdealIterator (Graph graph){
			this.graph = graph;
			this.stk = new Stack<IdealIteratorTuple>();
			this.returnedIdeals = new HashSet<String>(); 
			
			Ideal emptyIdeal = new Ideal(graph, new HashSet<Integer>(), new HashSet<Integer>());
			SubsetIterator<Integer> rootIterator = new SubsetIterator<Integer> (Arrays.asList(0));
			stk.push(new IdealIteratorTuple(emptyIdeal, rootIterator));
		}
		
		Ideal next(){
			while (!stk.isEmpty()){
				IdealIteratorTuple t = stk.pop();
				Ideal ideal =  t.ideal;
				SubsetIterator<Integer> iterator = t.iterator;
				while(iterator.hasNext()){
					List<Integer> nodesToAdd = iterator.next();
					Ideal newIdeal = ideal.addEmptyNodes(nodesToAdd);
					
					//skip if not new ideal
					if (!returnedIdeals.contains(Arrays.toString((newIdeal.labels)))){
						//add old ideal and iterator back to stack if still more
						if (iterator.hasNext()){
							stk.push(t);
						}
						//add new ideal to stack
						stk.push(new IdealIteratorTuple(newIdeal));
						//add new ideal to hash
						returnedIdeals.add(Arrays.toString(newIdeal.labels));
						//return our ideal
						return newIdeal;
					}
				}
			}
			return null;
		}
	}