package baum;

import java.util.List;
import java.util.function.Consumer;

import javax.swing.JFrame;
import javax.swing.JTree;

public class Tree<E> {
	private final E element;
	public final List<Tree<E>> childNodes;

	public Tree(E element, List<Tree<E>> childNodes) {
		super();
		this.element = element;
		this.childNodes = childNodes;
	}
	public Tree() {
		this(null,null);
	}
	public boolean isEmpty() {return element==null && childNodes==null;}
	
	public long count() {
		return isEmpty()
				?0
				:(1+childNodes.parallelStream().mapToLong(child->child.count()).sum());
	}
	public long count2() {
		if (isEmpty()) return 0;
		var result = 1L;
		for (var child:childNodes) {
			result = result+child.count2();
		}
		return result;
	}

	public long count3() {
		long [] result = {0L};
		fuerAlle(e -> result[0]++);
		return result[0];
	}
	
	public void fuerAlle(Consumer<? super E> action) {
		if (isEmpty()) return;
		action.accept(element);
		childNodes.stream().parallel().forEach(child->child.fuerAlle(action));
	}

	public void fuerAlle2(Consumer<? super E> action) {
		if (isEmpty()) return;
		action.accept(element);
		for (var child:childNodes) {
			child.fuerAlle2(action);
		}
	}
	
	public boolean contains(E el) {
		return !isEmpty() && 
				(element.equals(el)
			||childNodes.parallelStream().anyMatch(child->child.contains(el))); 
	}
	public boolean contains2(E el) {
		if (isEmpty()) return false;
		if (element.equals(el)) return true;
		for (var child:childNodes) {
			if (child.contains2(el)) return true;
		}
		return false;
	}
	
	@Override
	public String toString() {
		return element.toString();
	}
	
	public static void main(String[] args) {
		var windsor = new Tree<>("George"
				,List.of(new Tree<>("Elizabeth",List.of
						(new Tree<>("Charles",List.of())
								,new Tree<>("Anne",List.of())
								,new Tree<>("Edward",List.of())
								,new Tree<>("Phillip",List.of())
								)
						)
						,new Tree<>("Margrete",List.of())));
		System.out.println(windsor.count());
		System.out.println(windsor.count2());
		System.out.println(windsor.count3());
		System.out.println(windsor.contains("Edward"));
		System.out.println(windsor.contains("Wilhelm"));
		
		var jt = new JTree(new SecondModel<>(windsor));
		var f = new JFrame();
		f.add(jt);
		f.pack();
		f.setVisible(true);
		
		
		
	}
	
}
