package classifier;

import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Packet;
import weka.clusterers.EM;
import weka.core.Instance;
import weka.core.Instances;

/**
 * Expectation Maximization Clustering Approach
 * @author Andreas T. Meyer-Berg
 */
public class EMClustering extends BasicPacketClassifier {

	/**
	 * EM cluster which is used
	 */
	private EM clusterer;
	
	/**
	 * Initialize the clusterer
	 */
	public EMClustering() {
		clusterer = new EM();
	}
	
	@Override
	public void trainModel(Instances instances) {
		try {
			clusterer.buildClusterer(instances);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public double classifyInstance(Instance instance, Packet origin) throws Exception {
		/**
		 * Id of the closest cluster
		 */
		int x = clusterer.clusterInstance(instance);

		/*
		System.out.println(origin.getTextualRepresentation()+": cluster: "+x+" Dens: "+clusterer.logDensityForInstance(instance)+" joined: ");
		double[] joined = clusterer.logJointDensitiesForInstance(instance);
		for(int i = 0;i<joined.length;) {
			System.out.print(joined[i]);
			if(++i<joined.length)
				System.out.print(", ");
			else
				System.out.println("");
		}
		System.out.println("Distribution:");
		double[] distribution = clusterer.distributionForInstance(instance);
		for(int i = 0;i<distribution.length;) {
			System.out.print(distribution[i]);
			if(++i<distribution.length)
				System.out.print(", ");
			else
				System.out.println("");
		}
		
		double[] priors = clusterer.clusterPriors();
		System.out.println("Priors: ");
		for(int i = 0; i<priors.length; i++) {
			System.out.println("i="+i+": "+priors[i]);
		}
		double[][][] rest = clusterer.getClusterModelsNumericAtts();
		double[][] posteriori = rest[x];
		for(int i = 0; i<posteriori.length; i++) {
			System.out.println("Att "+i+": Mean: "+posteriori[i][0]+" Std: "+posteriori[i][1]+" ???: "+posteriori[i][2]+" Real: "+instance.value(i));
		}*/
		return (1-clusterer.distributionForInstance(instance)[x])*800;
	}

	@Override
	public long getClassificationStart() {
		return 3600000;
	}

	@Override
	public String getAlgoName() {
		return "EM";
	}

}