package main;

import fr.lip6.classifier.SMOSVM;
import hypothesis_validation.HoG_Functions;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;

import javax.imageio.ImageIO;

import preprocessing.Util;

public class CopyOfTestHoG {
	
	static int border_x = 48; /*pixels*/
	
	static int border_y = 16; /*pixels*/
	
	public static void main(String[] args) throws IOException {
		
		int pyramid_levels = 3;
		
		String input_image = args[0];
		
		String HoG_Norm = args[1];
		
		String HoG_Obj = args[2];
		
		int ranking_size = 100;
		
		double[][] ranking_list = init_ranking (ranking_size);
		
		BufferedImage in_image = ImageIO.read(new File(input_image)); 

		BufferedImage[] image_pyramid = Util.Build_Pyramid (in_image, pyramid_levels);
		
		ArrayList<Double> mean = new ArrayList<Double>();
		
		ArrayList<Double> deviation = new ArrayList<Double>();
		
		HoG_Functions.read_hog_vectors (mean, deviation, HoG_Norm);

		
		SMOSVM<double[]> cls = null;
		try {
    		ObjectInputStream obj = new ObjectInputStream(new FileInputStream(HoG_Obj));
    	    cls = (SMOSVM<double[]>) obj.readObject();
    	    obj.close();
    	}
    	catch (Exception e){
    		e.printStackTrace();
    	}

		
		for (int level = 0; level < pyramid_levels; level++) {
							
			int width = image_pyramid[level].getWidth();
			
			int height = image_pyramid[level].getHeight();
			
			System.err.printf("width : %d, height : %d\n", width, height);
			
			double[] image = new double[width*height];
			
			for (int i = 0; i < width - border_x; i++) {
				for (int j = 0; j < height - border_y; j++) {
					//System.err.printf("i : %d, j : %d, w : %d, h :%d\n", i, j, border_x, border_y);
					BufferedImage sub_image =  image_pyramid[level].getSubimage(i, j, border_x, border_y);
					double v = HoG_Functions.Get_HoG_Score (sub_image, mean, deviation, cls);
					int pos = (j + border_y/2) * width + (i + border_x/2);
					image[pos] = v;
					ranking (v, i, j, ranking_list, ranking_size);
				}
				if ((i % 25) == 0)
					System.err.printf("+ 25 lines : %d, %d\n", i, width - border_x);
			}
			Util.writeDoubletoPGM (image, width, height, -2, 2, "svm_"+level+"_");
			print_ranking (ranking_list, ranking_size, image_pyramid[level], "rank_"+level+".png");
		}		
	}
	
	public static double[][] init_ranking (int rank_size) {
		double[][] rank = new double[rank_size][3];
		for (int i = 0; i < rank_size; i++) {
			rank[i][0] = Double.MIN_VALUE;
			rank[i][1] = -1;
			rank[i][2] = -1;
		}
		return rank;
	}
	
	public static void ranking (double score, int x, int y, double[][] rank, int rank_size) {
		double min = Double.MAX_VALUE;
		int pos = Integer.MAX_VALUE;
		for (int i = 0; i < rank_size; i++) {
			if (rank[i][0] < min) {
				min = rank[i][0];
				pos = i;
			}
		}
		
		assert (pos != Integer.MAX_VALUE);
			
		if (rank[pos][0] < score) {
			rank[pos][0] = score;
			rank[pos][1] = x;
			rank[pos][2] = y;
		}
	}
	
	public static void print_ranking (double[][] rank, int rank_size, BufferedImage image, String name) {
		
		BufferedImage temp = Util.imageScale (image, 1.0);
		
		Graphics2D g = temp.createGraphics();
		g.setStroke(new BasicStroke(2.0f));		
		g.setColor(Color.yellow);
		
		for (int i = 0; i < rank_size; i++) {
			int x = (int)rank[i][1]; 
			
			int y = (int)rank[i][2];
			
			int w = border_x;
			
			int h = border_y;

			g.drawRect(x, y, w, h);
		}
		
		g.dispose();
		
		try {
			ImageIO.write(temp, "png", new File(name));
		}
		catch (Exception e) { 
				System.err.printf("cannot write image\n");
		}
		
	}
	
}
