package hypothesis_validation;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.imageio.ImageIO;

import descriptors.HoG;
import fr.lip6.classifier.SMOSVM;
import parameters.detection_arguments;
import preprocessing.Parser;
import preprocessing.Util;
import regrouping.Box;
import regrouping.Groupment;
import tracking.Atributes;

public class HoG_Functions {
	
	
	public static ArrayList<Atributes> HoG_Classification (
			BufferedImage image, 
			LinkedList<regrouping.Box> list,
			ArrayList<Double> hogmean,
			ArrayList<Double> hogstd,
			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);

			if (  (box.getDec() > 0) && (box.getCount() < detection_parameters.Get_Minimum_Grouping_Set()) ) {
				continue;
			}

			BufferedImage iBox = Util.getSubImage (image, box.getXMin()/2, box.getYMin()/2, box.getXMax()/2, box.getYMax()/2);

			double v = Get_HoG_Score (iBox, hogmean, hogstd, cls);
			
			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_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 int read_hog_vectors( ArrayList<Double> mean, ArrayList<Double> std, String hog_file)
	{
		int hog_size = -1;
		
		
		try {
			Parser obj = new Parser();
						
			LineNumberReader file = new LineNumberReader(new FileReader(hog_file));
			
			hog_size = Integer.parseInt(obj.getLineParameter (file, "\n", 0)); 
			
			for(int i = 0; i < hog_size; i++) {
				String[] s = obj.getTokens (file, "\n");
				mean.add( Double.parseDouble(s[0]));
			}
			for(int i = 0; i < hog_size; i++) {
				String[] s = obj.getTokens (file, "\n");
				std.add(Double.parseDouble(s[0]));
			}

			file.close();
		}
		catch (IOException e) {
			System.err.println("exception: failed to read hog files!");
			e.printStackTrace();
		}
		return hog_size;
	}
	
    
	public static double Get_HoG_Score (BufferedImage image, ArrayList<Double> mean, ArrayList<Double> std, SMOSVM<double[]> cls) 
    {
		HoG hog = new HoG();
    	//double[] hog_descriptor = hog.HoGFixedNumberOfCells (image, 4, 4, 2); 
    	double[] hog_descriptor = hog.hog(image);
    	if (hog_descriptor == null) {
    		return -Double.MAX_VALUE;
    	}
    	for(int x = 0; x < hog_descriptor.length; x++) {
    		hog_descriptor[x] = (hog_descriptor[x]-mean.get(x))/std.get(x);
    	} 
    	return cls.valueOf(hog_descriptor); 
    }
	

}
