package nl.tudelft.dnainator.ui.drawables.strains;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javafx.collections.MapChangeListener;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import nl.tudelft.dnainator.core.SequenceNode;
import nl.tudelft.dnainator.ui.ColorServer;
import nl.tudelft.dnainator.ui.drawables.Drawable;

/**
 * The {@link ClusterDrawable} class represents the mid level object in the viewable model.
 */
public class ClusterDrawable extends Group implements Drawable {
	private static final int CLUSTER_SIZE = 3;
	private static final int PIETHRESHOLD = 10;
	private List<SequenceNode> clustered;
	private Set<String> sources;
	private Text label;
	private Pie pie;

	/**
	 * Construct a new mid level {@link ClusterDrawable} using the default graph.
	 * @param colorServer the {@link ColorServer} to bind to.
	 * @param clustered	the clustered {@link SequenceNode}s in this cluster.
	 */
	public ClusterDrawable(ColorServer colorServer, List<SequenceNode> clustered) {
		this.clustered = clustered;
		this.sources = clustered.stream()
				.flatMap(e -> Arrays.asList(e.getSource().split(",")).stream())
				.collect(Collectors.toSet());

		label = new Text(Integer.toString(clustered.size()));
		label.setStyle("-fx-font-size: 2pt");

		if (sources.size() > PIETHRESHOLD) {
			getChildren().add(new Circle(CLUSTER_SIZE));
		} else {
			colorServer.addListener(this::onColorServerChanged);

			List<String> collect = sources.stream()
					.map(e -> colorServer.getColor(e))
					.filter(e -> e != null)
					.collect(Collectors.toList());
			pie = new Pie(CLUSTER_SIZE, collect);
			getChildren().add(pie);
		}
		getChildren().add(label);
	}

	private void onColorServerChanged(
			MapChangeListener.Change<? extends String, ? extends String> change) {
		if (!sources.contains(change.getKey())) {
			return;
		} else if (change.wasAdded()) {
			addStyle(change.getValueAdded());
		} else if (change.wasRemoved()) {
			removeStyle(change.getValueRemoved());
		}
	}

	@Override
	public void addStyle(String style) {
		pie.getStyles().add(style);
	}

	@Override
	public void removeStyle(String style) {
		pie.getStyles().remove(style);
	}

	/**
	 * @return the {@link SequenceNode}s in this cluster.
	 */
	public List<SequenceNode> getClustered() {
		return clustered;
	}
}

@@ -627,24 +627,284 @@
 int 
-CLUSTER_SIZE = 3
+SINGLE = 1;%0A%09private static final int SMALL = 3;%0A%09private static final int MEDIUM = 10;%0A%09private static final double SINGLE_RADIUS = 2;%0A%09private static final double SMALL_RADIUS = 4;%0A%09private static final double MEDIUM_RADIUS = 5;%0A%09private static final double LARGE_RADIUS = 6
 ;%0A%09p
@@ -1624,16 +1624,119 @@
 2pt%22);%0A%0A
+%09%09draw(colorServer);%0A%09%7D%0A%0A%09private void draw(ColorServer colorServer) %7B%0A%09%09double radius = getRadius();%0A%0A
 %09%09if (so
@@ -1798,28 +1798,22 @@
  Circle(
-CLUSTER_SIZE
+radius
 ));%0A%09%09%7D 
@@ -2045,20 +2045,14 @@
 Pie(
-CLUSTER_SIZE
+radius
 , co
@@ -2118,24 +2118,308 @@
 label);%0A%09%7D%0A%0A
+%09private double getRadius() %7B%0A%09%09int nChildren = clustered.size();%0A%0A%09%09if (nChildren == SINGLE) %7B%0A%09%09%09return SINGLE_RADIUS;%0A%09%09%7D else if (nChildren %3C= SMALL) %7B%0A%09%09%09return SMALL_RADIUS;%0A%09%09%7D else if (nChildren %3C= MEDIUM) %7B%0A%09%09%09return MEDIUM_RADIUS;%0A%09%09%7D else %7B%0A%09%09%09return LARGE_RADIUS;%0A%09%09%7D%0A%09%7D%0A%0A
 %09private voi

Set cluster size on the amount of clustered nodes