package be.kuleuven.cs.distrinet.rejuse.tree;

import java.util.Collections;
import java.util.List;

import be.kuleuven.cs.distrinet.rejuse.action.Nothing;
import be.kuleuven.cs.distrinet.rejuse.function.Function;
import be.kuleuven.cs.distrinet.rejuse.predicate.UniversalPredicate;

import com.google.common.collect.ImmutableList;

/**
 * A pruned tree structure provides a pruned view on a tree structure. The
 * pruned tree structure contains only those elements satisfy its predicate.
 * In addition, by using a {@link TreePredicate}, it avoids traversing the
 * entire underlying tree structure by skipping subtrees of which the
 * predicate indicates that it can never match elements.
 *  
 * @author Marko van Dooren
 *
 * @param <T> The type of the nodes in the tree structure.
 */
public class PrunedTreeStructure<T> extends TreeStructure<T> {

	public PrunedTreeStructure(TreeStructure<T> underLyying, TreePredicate<T, Nothing> predicate) {
		_underLying = underLyying;
		_predicate = predicate;
	}
	
	private TreeStructure<T> _underLying;
	
	@Override
	public T node() {
	  return _underLying.node();
	}
	
	@Override
	public T parent() {
		// Not a skipper
		return _underLying.parent();
//		return nearestAncestor(node, new UniversalPredicate<T, Nothing>(type()) {
//
//			@Override
//			public boolean uncheckedEval(T t) throws Nothing {
//				return PrunedTreeStructure.this.eval(t);
//			}
//		});
	}

	@Override
	public List<? extends T> children() {
		if(canSucceedBeyond(node())) {
			return _underLying.children();
		} else {
			return Collections.EMPTY_LIST;
		}
	}
	
//	/**
//	 * Navigate the 
//	 * @param nodes
//	 * @return
//	 * @throws E 
//	 * @throws Nothing 
//	 */
//	private List<? extends T> skip(List<? extends T> nodes, Function<T,TreeStructure<T>,Nothing> treeSelector) throws Nothing {
//		ImmutableList.Builder<T> builder = ImmutableList.builder(); 
//		for(T node: nodes) {
//			if(eval(node)) {
//				builder.add(node);
//			} else {
//				if(canSucceedBeyond(node)) {
//					builder.addAll(skip(treeSelector.apply(node).children(node),treeSelector));
//				}
//			}
//		}
//		return builder.build();
//	}
	
	public final boolean canSucceedBeyond(T node) {
		return _predicate.canSucceedBeyond(node);
	}
	
	private TreePredicate<T, Nothing> _predicate;
//	public abstract boolean eval(T node);

	@Override
	public TreeStructure<T> tree(T element) {
	  return new PrunedTreeStructure<>(_underLying.tree(element), _predicate);
	}
	
//	public abstract Class<T> type();

}

@@ -1146,27 +1146,8 @@
 ) %7B%0A
-%09%09// Not a skipper%0A
 %09%09re
@@ -1177,951 +1177,178 @@
 ();%0A
-//%09%09return nearestAncestor(node, new UniversalPredicate%3CT, Nothing%3E(type()) %7B%0A//%0A//%09%09%09@Override%0A//%09%09%09public boolean uncheckedEval(T t) throws Nothing %7B%0A//%09%09%09%09return PrunedTreeStructure.this.eval(t);%0A//%09%09%09%7D%0A//%09%09%7D);%0A%09%7D%0A%0A%09@Override%0A%09public List%3C? extends T%3E children() %7B%0A%09%09if(canSucceedBeyond(node())) %7B%0A%09%09%09return _underLying.children();%0A%09%09%7D else %7B%0A%09%09%09return Collections.EMPTY_LIST;%0A%09%09%7D%0A%09%7D%0A%09%0A//%09/**%0A//%09 * Navigate the %0A//%09 * @param nodes%0A//%09 * @return%0A//%09 * @throws E %0A//%09 * @throws Nothing %0A//%09 */%0A//%09private List%3C? extends T%3E skip(List%3C? extends T%3E nodes, Function%3CT,TreeStructure%3CT%3E,Nothing%3E treeSelector) throws Nothing %7B%0A//%09%09ImmutableList.Builder%3CT%3E builder = ImmutableList.builder(); %0A//%09%09for(T node: nodes) %7B%0A//%09%09%09if(eval(node)) %7B%0A//%09%09%09%09builder.add(node);%0A//%09%09%09%7D else %7B%0A//%09%09%09%09if(canSucceedBeyond(node)) %7B%0A//%09%09%09%09%09builder.addAll(skip(treeSelector.apply(node).children(node),treeSelector));%0A//%09%09%09%09%7D%0A//%09%09%09%7D%0A//%09%09%7D%0A//%09%09return builder.build();%0A//
+%09%7D%0A%0A%09@Override%0A%09public List%3C? extends T%3E children() %7B%0A%09%09if(canSucceedBeyond(node())) %7B%0A%09%09%09return _underLying.children();%0A%09%09%7D else %7B%0A%09%09%09return Collections.EMPTY_LIST;%0A%09%09%7D%0A
 %09%7D%0A%09
@@ -1496,49 +1496,8 @@
 ate;
-%0A//%09public abstract boolean eval(T node);
 %0A%0A%09@
@@ -1633,43 +1633,6 @@
 %7D%0A%09%0A
-//%09public abstract Class%3CT%3E type();%0A%0A
 %7D%0A

remove commented code