package de.ugoe.cs.cpdp.dataselection;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.collections4.list.SetUniqueList;
import org.apache.commons.math3.util.MathArrays;

import weka.core.Attribute;
import weka.core.Instance;
import weka.core.Instances;

/**
 * Filter according to F. Peters, T. Menzies, and A. Marcus: Better Cross Company Defect Prediction
 * <br><br>
 * This filter does not work, the paper has been withdrawn. 
 * @author Steffen Herbold
 */
@Deprecated
public class PetersFilter implements IPointWiseDataselectionStrategy {

	
	/**
	 * @see de.ugoe.cs.cpdp.IParameterizable#setParameter(java.lang.String)
	 */
	@Override
	public void setParameter(String parameters) {
		// dummy
	}

	/**
	 * @see de.ugoe.cs.cpdp.dataselection.IPointWiseDataselectionStrategy#apply(weka.core.Instances, weka.core.Instances)
	 */
	@Override
	public Instances apply(Instances testdata, Instances traindata) {
		final Attribute classAttribute = testdata.classAttribute();
			
		final double[][] testDoubles = new double[testdata.numInstances()][testdata.numAttributes()];
		for( int i=0; i<testdata.numInstances() ; i++ ) {
			Instance instance = testdata.instance(i);
			int tmp = 0;
			for( int j=0 ; j<testdata.numAttributes(); j++ ) {
				if( testdata.attribute(j)!=classAttribute ) {
					testDoubles[i][tmp++] = instance.value(j);
				}
			}
		}
		
		final double[][] trainDoubles = new double[traindata.numInstances()][testdata.numAttributes()];
		for( int i=0; i<traindata.numInstances() ; i++ ) {
			Instance instance = traindata.instance(i);
			int tmp = 0;
			for( int j=0 ; j<testdata.numAttributes(); j++ ) {
				if( testdata.attribute(j)!=classAttribute ) {
					trainDoubles[i][tmp++] = instance.value(j);
				}
			}
		}
		
		final List<List<Integer>> fanList = new ArrayList<List<Integer>>(testdata.numInstances());
		for( int i=0; i<testdata.numInstances(); i++ ) {
			fanList.add(new LinkedList<Integer>());
		}
		
		for( int i=0; i<traindata.numInstances(); i++ ) {
			double minDistance = Double.MAX_VALUE;
			int minIndex = 0;
			for( int j=0; j<testdata.numInstances(); j++ ) {
				double distance = MathArrays.distance(trainDoubles[i], testDoubles[j]);
				if( distance<minDistance ) {
					minDistance = distance;
					minIndex = j;
				}
			}
			fanList.get(minIndex).add(i);
		}
		
		final SetUniqueList<Integer> selectedIndex = SetUniqueList.setUniqueList(new LinkedList<Integer>());
		for( int i=0; i<testdata.numInstances(); i++ ) {
			double minDistance = Double.MAX_VALUE;
			int minIndex = -1;
			for( Integer j : fanList.get(i) ) {
				double distance = MathArrays.distance(testDoubles[i], trainDoubles[j]);
				if( distance<minDistance && distance>0.0d ) {
					minDistance = distance;
					minIndex = j;
				}
			}
			if( minIndex!=-1 ) {
				selectedIndex.add(minIndex);
			}
		}
		
		final Instances selected = new Instances(testdata);
		selected.delete();
		for( Integer i : selectedIndex) {
			selected.add(traindata.instance(i));
		}
		return selected;
	}

}
