package hypothesis_validation;

import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.LinkedList;

import parameters.detection_arguments;
import preprocessing.Parser;
import preprocessing.Util;
import regrouping.Box;

import tracking.Atributes;
import descriptors.HoG;
import fr.lip6.classifier.Classifier;
import fr.lip6.classifier.SMOSVM;

public class HoG_Score {
		
	public ArrayList<Atributes> HoG_Classification (
			BufferedImage image, 
			LinkedList<regrouping.Box> list,
			detection_arguments detection_parameters,
			String image_name)  {

		ArrayList<Atributes> set_D = new ArrayList<Atributes>();
		
    	SMOSVM<double[]> cls = null;
		try {
    		ObjectInputStream obj = new ObjectInputStream(new FileInputStream(detection_parameters.hog_obj));
    	    cls = (SMOSVM<double[]>) obj.readObject();
    	    obj.close();
    	}
    	catch (Exception e){
    		e.printStackTrace();
    	}
    	
    	Parser parser = new Parser();
    	
    	ArrayList<String> hog_parameters = parser.Get_Array_List (detection_parameters.hog_parameters);
		
		for (int i = 0; i < list.size(); i++) { 			

			Box box = list.get(i);

			if (  (box.getDec() > 0) && (box.getCount() < detection_parameters.Get_Minimum_Grouping_Set()) ) {
				continue;
			}
			
			int x = box.getXMin()/2;
            int y = box.getYMin()/2;
            int w = (box.getXMax()-box.getXMin())/2;
            int h = (box.getYMax()-box.getYMin())/2;	
			
			BufferedImage region = getSubImage (image, x, y, w, h);
			
			double v;
			
			if (detection_parameters.use_hog) {
			   v = get_score (region, cls, hog_parameters);
			}
			else {
		       v = 1.0;
			}
			
			if ((v >= 0)) {
				box.setValid (-1.0); 
				
				Atributes new_box = new Atributes();
				
				new_box.set_x (x);
				new_box.set_y (y);
				new_box.set_width (w);
				new_box.set_height (h);
				
				
				new_box.set_C(x + w/2.0, y + h/2.0);
				new_box.set_V(w/2.0, 0.0);
				new_box.set_U(0.0, h/2.0);				
				
				new_box.set_label(String.format("I:%02d", i)); /*Adicionar Re, ou média de Rd e Re?*/
				
				
				//new_box.set_number_of_characters(box.getCount());
				//new_box.set_flag (false);
				//new_box.set_fp (0);
				//new_box.set_weight (-Double.MIN_VALUE);				
				//new_box.image = region;
				set_D.add(new_box);
			}
			else { 
				box.setValid (1.0);
			}
		}
		
		return set_D;
	}
	
	public BufferedImage getSubImage (BufferedImage image, int x1, int y1, int w1, int h1) {

        int margin = (int)(0.15*h1 + 0.5);

        int xmin = x1;
        int xmax = x1 + w1 - 1;
        int ymin = y1 - margin;
        int ymax = y1 + h1 - 1 + margin;

        BufferedImage region = Util.getSubImage(image, xmin, ymin, xmax, ymax);

        return region;
    }
	
	public double get_score (
			BufferedImage image, 
			Classifier cls,
			ArrayList<String> list ) 
    {	
		boolean debug = false;
		
		double[] descriptor = get_descriptor (debug, image, list);

    	return cls.valueOf (descriptor);  
    }
	
	public void print_descriptor (
			BufferedImage image, 
			ArrayList<String> list ) 
    {
		boolean debug = true;
		double descriptor[] = get_descriptor (debug, image, list);
		for (int i = 0; i < descriptor.length; i++) {
			System.out.printf("%d : %f\n", i, descriptor[i]);
		}
    }
	
	public double[] get_descriptor (
			boolean debug,
			BufferedImage image, 
			ArrayList<String> list ) 
    {			
			
		int new_height = Integer.parseInt(list.get(0));     
		
        int number_of_cells_x = Integer.parseInt(list.get(1));
		
        int number_of_cells_y = Integer.parseInt(list.get(2));
			
		int bins_per_cell = Integer.parseInt(list.get(3));
		
		boolean image_normalization = Boolean.parseBoolean(list.get(4)); 
		
		String image_normalization_weight = list.get(5);
		
		double image_normalization_weight_radius = Double.parseDouble(list.get(6));
		
		String gradient_option = list.get(7);
		
		String histogram_normalization_metric = list.get(8);
		
		String weight_function = list.get(9);
		
		boolean deformable_weights = Boolean.parseBoolean(list.get(10));
		
		HoG hog = new HoG();
		
		double[] descriptor = hog.hog_descriptor ( 
				debug,
				image, 
		        new_height,        
		        number_of_cells_x,
		        number_of_cells_y,
		        bins_per_cell,
		        image_normalization,
		        image_normalization_weight, 
		        image_normalization_weight_radius,
		        gradient_option,
		        histogram_normalization_metric,
		        weight_function,
		        deformable_weights );	
		
		return descriptor;
    }
}
