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.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 static 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));
    	    cls = (SMOSVM<double[]>) obj.readObject();
    	    obj.close();
    	}
    	catch (Exception e){
    		e.printStackTrace();
    	}
		
		for (int i = 0; i < list.size(); i++) { 			

			Box box = list.get(i);

			/*TO VERIFY*/
			int margin = 1;//(int)(0.5*(box.getYMax() - box.getYMin() + 1)*1.0/detection_parameters.Get_New_Resized_Height() + 0.5);

			System.err.printf("HoG Margin : %d\n", margin);

			if (  (box.getDec() > 0) && (box.getCount() < detection_parameters.Get_Minimum_Grouping_Set()) ) {
				continue;
			}
			
			int x = box.getXMin()/2;
            int y = (int) text_region.getY();
            int w = (int) text_region.getW();
            int h = (int) text_region.getH();	
			
			BufferedImage region = getSubImage (image, x, y, w, h);
			
			BufferedImage iBox = Util.getSubImage (image, box.getXMin()/2-margin, box.getYMin()/2-margin, box.getXMax()/2+margin, box.getYMax()/2+margin);

			double v;
			
			if (detection_parameters.use_hog) {
			   v = Get_HoG_Score (iBox, hogmean, hogstd, cls, detection_parameters);
			}
			else {
		       v = 1.0;
			}
			
			if ((v >= 0)) 
			{
				box.setValid (-1.0); 

				/*copying the detected regions*/

				int x = box.getXMin()/2; 

				int y = box.getYMin()/2;

				int w = (box.getXMax()-box.getXMin())/2;

				int h = (box.getYMax()-box.getYMin())/2;

				Atributes new_box = new Atributes();

				/*Adicionar uma borda de -1 e +1 sobre essa area - CUIDADO*/

				new_box.set_x (x);

				new_box.set_y (y);

				new_box.set_width (w);

				new_box.set_height (h);
				
				new_box.set_number_of_characters(box.getCount());

				new_box.set_flag (false);
				
				new_box.set_fp (0);

				//new_box.set_weight (box.getDec()); //Ver isso melhor depois o PESO
				new_box.set_weight (-Double.MIN_VALUE);// -> COMENTAR ISSO PARA O TRACKING
				
				new_box.image = iBox;

				set_D.add(new_box);

				//System.err.println("AQUI NAS CAIXAS MEU");

				//System.err.printf("A ind: %d, x : %d, y : %d, w :%d, h :%d\n", i, x, y, w, h);
				
				/*try {
					ImageIO.write(iBox, "png", new File("./positives/"+image_name+String.format("%03d", i)+".png"));
					//ImageIO.write(Original, "png", new File(out_path + String.format("%05d", iframe) + "/detection.png"));
				}
				catch (Exception e) {
					System.err.println("cannot store image");
				}*/

			}
			else 
			{ 
				/*try {
					ImageIO.write(iBox, "png", new File("./negatives/"+image_name+String.format("%03d", i)+".png"));
					//ImageIO.write(Original, "png", new File(out_path + String.format("%05d", iframe) + "/detection.png"));
				}
				catch (Exception e) {
					System.err.println("cannot store image");
				}*/ 
				box.setValid (1.0);
			}
		}
		
		/*BufferedImage output = Util.imageScale (image, 1.0);
		
		Util.write_boxes (output, list, "./hog/"+image_name);  

		long stop = System.currentTimeMillis(); 
		//System.out.println("Segmentation : " + (stop-start)); 
		
		Groupment.Dispose_Small_Regions_Agroupments (output, list, detection_parameters);
			
		if (detection_parameters.write_image) {
			
			try {
				ImageIO.write(output, "png", new File("testando.png"));
				//ImageIO.write(Original, "png", new File(out_path + String.format("%05d", iframe) + "/detection.png"));
			}
			catch (Exception e) {
				System.err.println("cannot store image");
			} 
		} */
		
		System.err.printf("O TAMANHO DO CONJUNTO SET_D EH: %d\n", set_D.size()); 
		
		
		return set_D;
	}
	
	public static 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;
    }
}
