package common.graph;

import common.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

class ConnectedComponent<T extends Vertex<T>> {
	
	private final int size;
	private final Set<T> core;
	private Set<T> edge, cuttingEdge;
	
	private final List<T> unassignedNodes;
	
	@SafeVarargs
	ConnectedComponent(int size, List<T> unassignedNodes, Consumer<Set<T>>... contractEvents) {
		this(size, unassignedNodes, Arrays.asList(contractEvents));
	}
	
	ConnectedComponent(int size, List<T> unassignedNodes, Collection<Consumer<Set<T>>> contractEvents) {
		this.size = size;
		this.growthListeners = new ArrayList<>(contractEvents);
		
		this.unassignedNodes = unassignedNodes;
		
		this.cuttingEdge = new HashSet<>(size);
		this.edge = new HashSet<>(size);
		this.core = new HashSet<>(size);
	}
	
	boolean cuttingEdgeIsEmpty(){
		return cuttingEdge.isEmpty();
	}
	
	void grow(){
		for(T edgeNode : edge){
			addAll(edgeNode.neighbors());
		}
		unassignedNodes.removeAll(cuttingEdge);
	}
	
	private final List<Consumer<Set<T>>> growthListeners;
	
	Set<T> contract(){
		triggerGrowthListeners();
		
		core.addAll(edge);
		edge = cuttingEdge;
		cuttingEdge = new HashSet<>((size - core.size() - edge.size()) * Sets.JAVA_UTIL_HASHSET_SIZE_FACTOR);
		
		return core;
	}
	
	private void triggerGrowthListeners(){
		growthListeners.stream().forEach( (c)->c.accept(cuttingEdge) );
	}
	
	void add(T vertex){
		if( !core.contains(vertex) && !edge.contains(vertex) ){
			cuttingEdge.add(vertex);
		}
	}
	
	void addAll(Collection<? extends T> vertices){
		for(T vertex : vertices){
			add(vertex);
		}
	}
}

@@ -40,61 +40,8 @@
 ts;%0A
-import java.util.ArrayList;%0Aimport java.util.Arrays;%0A
 impo
@@ -139,44 +139,8 @@
 Set;
-%0Aimport java.util.function.Consumer;
 %0A%0Acl
@@ -323,22 +323,8 @@
 ;%0A%09%0A
-%09@SafeVarargs%0A
 %09Con
@@ -376,297 +376,31 @@
 odes
-, Consumer%3CSet%3CT%3E%3E... contractEvents) %7B%0A%09%09this(size, unassignedNodes, Arrays.asList(contractEvents));%0A%09%7D%0A%09%0A%09ConnectedComponent(int size, List%3CT%3E unassignedNodes, Collection%3CConsumer%3CSet%3CT%3E%3E%3E contractEvents) %7B%0A%09%09this.size = size;%0A%09%09this.growthListeners = new ArrayList%3C%3E(contractEvents);%0A%09%09
+) %7B%0A%09%09this.size = size;
 %0A%09%09t
@@ -755,114 +755,26 @@
 %0A%09%0A%09
-private final List%3CConsumer%3CSet%3CT%3E%3E%3E growthListeners;%0A%09%0A%09Set%3CT%3E contract()%7B%0A%09%09triggerGrowthListeners();%0A%09%09
+Set%3CT%3E contract()%7B
 %0A%09%09c
@@ -944,119 +944,8 @@
 %7D%0A%09%0A
-%09private void triggerGrowthListeners()%7B%0A%09%09growthListeners.stream().forEach( (c)-%3Ec.accept(cuttingEdge) );%0A%09%7D%0A%09%0A
 %09voi

remove growth-listeners from ConnectedComponent