import java.io.*;
import java.util.Vector;

import cas.Point;

/**
 * Driver class which tests the performance,speed wise, of nearest 
 * neighbor search algorithms.
 * To run the program on a specific algorithm:
 *               'java NNTest N Neighbor_File_Name Points_File_Name'
 * where N                    - Number of algorithm to use.
 *                              1 - Naive.
 *                              2 - kD-Tree.
 *       Neighbor_File_Name   - Set of points which will be searched.
 *       Points_File_Name     - Find the nearest neighbor to these points in 
 *                              the other point set.
 * 
 * @author Ziv Yaniv
 */
public class NNTest {
    public static void main(String[] args) {
	final int NAIVE = 1;
	final int KD_TREE = 2;

	NearestNeighbor nn = null; 

	if(args.length != 3) {
	    System.err.println("Wrong number of arguments.\n"+
			       "Usage: java NNTest <algorithm_number> "+
			       "<neighbors> <points>");
	    System.exit(1);
	}
 
                 	//load the points and choose the algorithm
	Vector neighbors = loadPoints(args[1]);
	Vector points    = loadPoints(args[2]);

	switch(Integer.parseInt(args[0])) {
	case NAIVE:
	    nn = new NaiveNearestNeighbor(neighbors,false); 
	    break;
	case KD_TREE:
	    int binSize = 256;
	    nn = new KDTree(neighbors,binSize,false); 
	    break;
	}

             	//perform the nearest neighbor search, and subtract
            	//the nearest neighbor element wise (when the points are
          	//a sub set of each other all results should be [0,0,0]). 
	int n = points.size();
	for(int i=0; i<n; i++) {
	    Point p = new Point(nn.find((Point)points.elementAt(i)));
	    p.sub((Point)points.elementAt(i));
	    System.out.println(i+""+p);
	}
    }
  
   /**
    * Load a vector of points from a file into which it was
    * serialized.
    * @param fileName The file to read from.
    * @param return Returns a Vector containing Point data.
    * @see cas.Point
    */ 
    public static Vector loadPoints(String fileName) {
	try {
	    ObjectInputStream in = 
		new ObjectInputStream(new FileInputStream(fileName));
	    Vector res = (Vector) in.readObject();
	    in.close(); 
	    return res;
        }catch(Exception except) {
	    System.out.println("Error while loading input file ("+
			       fileName+").");
	}
	return null; //pacify the java compiler, will never get here
    }
}

