package main;

import fr.lip6.classifier.Classifier;
import hypothesis_validation.HoG_Functions;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import parameters.detection_arguments;
import parameters.io_arguments;
import preprocessing.Parser;
import preprocessing.Util;
import tracking.Atributes;
import xml.Icdar;
import classification.SVM;
import classification.SVM_DATA;

public class Main {

	/*Main function to perform text detection or text tracking*/
	public static void main (String[] arguments) 
	throws FileNotFoundException, ClassNotFoundException, IOException {
		
		io_arguments io_parameters = new io_arguments();

		/*Reading the input/output parameters (in and output paths, ...)*/
		io_parameters.parsing(arguments);
		
		ArrayList<SVM> svm_descriptors = new ArrayList<SVM>();
		
		ArrayList<SVM_DATA> svm_classifiers = new ArrayList<SVM_DATA>();
		
		/*Reading the text detection file parameters*/
		detection_arguments detection_parameters = new detection_arguments(io_parameters.get_detection_parameters_file());
		
		/*Loading the trained svm classifiers*/
		if (detection_parameters.svm_option) {
			reading_svm_descriptors (svm_descriptors, detection_parameters);
		}
		else {			
			reading_svm_classifiers (svm_classifiers, detection_parameters);
		}
		
		if (io_parameters.get_option().equals("d")) {

			/*Text Detection*/
			try {
				/*Reading the image*/
				BufferedImage in_image = ImageIO.read(new File(io_parameters.get_in_image()));

				/*Performing Text Detection*/
				ArrayList<Atributes> set_D = TextDetection.Detection (in_image, svm_descriptors, svm_classifiers, io_parameters, detection_parameters);

				/*Writing an image with the boxes found by the detection step*/
				Util.write_set_regions (in_image, set_D, io_parameters, "", "d", -1); 

				/*Writing an XML file with the boxes found by the detection step*/
				Icdar.toXML (io_parameters.get_xml_header(), io_parameters.get_xml_name(), in_image.getWidth(), in_image.getHeight(), set_D, detection_parameters);

			} catch (IOException e) {
				System.err.println("error: unable to open the image: " + io_parameters.get_in_image());
				System.exit(1);
			}			
		}
		else if (io_parameters.get_option().equals("l")) {
			/*Text Detection - List Mode*/

			Parser parser = new Parser();

			LineNumberReader image_list = parser.Open_File (io_parameters.get_image_list());
			
			while(true) {
				/*Reseting the detection parameters*/
				detection_parameters = new detection_arguments(io_parameters.get_detection_parameters_file());
								
				/*Reading the image*/
				String image_name = Util.Get_Name (image_list);
				
				BufferedImage in_image = Util.Get_Image (image_name);

				if (in_image == null) { break; }
				
				int position = image_name.lastIndexOf("/");
				
				if (position == -1) { position = 0; } else { position += 1; }
				
				String sub_string = image_name.substring(position, image_name.lastIndexOf("."));
				
				io_parameters.information = sub_string;
				
				io_parameters.set_xml_header(sub_string);
				
				io_parameters.set_xml_name (sub_string);

				/*Performing Text Detection*/
				ArrayList<Atributes> set_D = TextDetection.Detection (in_image, svm_descriptors, svm_classifiers, HoG_mean, HoG_std, io_parameters, detection_parameters);
				
				/*Writing an image with the boxes found by the detection step*/
				Util.write_set_regions (in_image, set_D, io_parameters, sub_string + "", "l", -1); 

				/*Writing an XML file with the boxes found by the detection step*/
				Icdar.toXML (sub_string, io_parameters.get_out_path() + io_parameters.get_xml_name() + ".xml", in_image.getWidth(), in_image.getHeight(), set_D, detection_parameters);
			}
		}
		else if (io_parameters.get_option().equals("t")){
			/*Text Detection and Tracking*/
			TextTracking.Tracking (svm_descriptors, svm_classifiers, HoG_mean, HoG_std, io_parameters, detection_parameters);
		}
	}
	
	public static BufferedImage Get_Image (LineNumberReader file)
	{
		Parser parser = new Parser();

		BufferedImage image = null;

		String[] s = parser.getTokens (file, "\n");

		if (s == null)
			return null;

		try {
			image = ImageIO.read (new File(s[0]));
    	} catch (IOException e) {
			System.err.println("Failed to open image : " + s[0]);
		}
		return image;
	}
	
	
	/*Loading the trained svm classifiers*/
	static void reading_svm_descriptors (ArrayList<SVM> svm_descriptors, detection_arguments detection_parameters) {
		
		long start;
		
		/*Loading the trained fourier svm classifier*/
		start = System.currentTimeMillis();
		SVM fourier = new SVM();
		fourier.Reads_SVM_Model_From_Ascii_File (detection_parameters.fourier);
		svm_descriptors.add(fourier);
		Util.Compute_Processing_Time (start, "Fourier SVM C");
		
		/*Loading the trained polar svm classifier*/
		start = System.currentTimeMillis();
		SVM polar = new SVM();
		polar.Reads_SVM_Model_From_Ascii_File (detection_parameters.polar);
		svm_descriptors.add(polar);
		Util.Compute_Processing_Time (start, "Polar SVM C");
		
		/*Loading the trained zernike svm classifier*/
		start = System.currentTimeMillis();
		SVM zernike = new SVM();
		zernike.Reads_SVM_Model_From_Ascii_File (detection_parameters.zernike);
		svm_descriptors.add(zernike);
		Util.Compute_Processing_Time (start, "Zernike SVM C");
		
		/*Loading the trained svm classifier composed by all the previously descriptors (fourier, polar and zernike)*/
		start = System.currentTimeMillis();
		SVM all = new SVM();
		all.Reads_SVM_Model_From_Ascii_File (detection_parameters.all);
		svm_descriptors.add(all);
		Util.Compute_Processing_Time (start, "All SVM C");
	}
	
	static void reading_svm_classifiers (ArrayList<SVM_DATA> svm_classifiers, detection_arguments detection_parameters) {
		
		Parser parser = new Parser();
		
		try {
			long start;
			
			/*Reading Fourier SVM object and Fourier normalization file (mean and deviation+)*/
			start = System.currentTimeMillis();
			SVM_DATA fourier = new SVM_DATA();
			ObjectInputStream fourier_object = new ObjectInputStream(new FileInputStream(detection_parameters.fourier)); 
			fourier.cls = (Classifier) fourier_object.readObject();
			fourier_object.close();
			LineNumberReader fourier_file = new LineNumberReader(new FileReader(detection_parameters.fourier_normalization));
			int fourier_size = Integer.parseInt(parser.getLineParameter (fourier_file, "\n", 0)); 
			fourier.mean = parser.Get_Data (fourier_size, fourier_file);
    		fourier.deviation = parser.Get_Data (fourier_size, fourier_file); 
    		fourier_file.close(); 
    		svm_classifiers.add(fourier);
       		Util.Compute_Processing_Time (start, "Fourier SVM java");
    		
    		/*Reading Polar SVM object and Polar normalization file (mean and deviation+)*/
    		start = System.currentTimeMillis();
			SVM_DATA polar = new SVM_DATA();
			ObjectInputStream polar_object = new ObjectInputStream(new FileInputStream(detection_parameters.polar)); 
			polar.cls = (Classifier) polar_object.readObject();
			polar_object.close();
			LineNumberReader polar_file = new LineNumberReader(new FileReader(detection_parameters.polar_normalization));
			int polar_size = Integer.parseInt(parser.getLineParameter (polar_file, "\n", 0)); 
			polar.mean = parser.Get_Data (polar_size, polar_file);
    		polar.deviation = parser.Get_Data (polar_size, polar_file); 
    		polar_file.close(); 
    		svm_classifiers.add(polar);
    		Util.Compute_Processing_Time (start, "Polar SVM java");
    		
    		/*Reading Zernike SVM object and Zernike normalization file (mean and deviation+)*/
    		start = System.currentTimeMillis();
    		SVM_DATA zernike = new SVM_DATA();
			ObjectInputStream zernike_object = new ObjectInputStream(new FileInputStream(detection_parameters.zernike)); 
			zernike.cls = (Classifier) zernike_object.readObject();
			zernike_object.close();
			LineNumberReader zernike_file = new LineNumberReader(new FileReader(detection_parameters.zernike_normalization));
			int zernike_size = Integer.parseInt(parser.getLineParameter (zernike_file, "\n", 0)); 
			zernike.mean = parser.Get_Data (zernike_size, zernike_file);
			zernike.deviation = parser.Get_Data (zernike_size, zernike_file); 
			zernike_file.close(); 
    		svm_classifiers.add(zernike);
    		Util.Compute_Processing_Time (start, "Zernike SVM java");
    		
    		/*Reading the combination of all SVM object and its normalization file (mean and deviation+)*/
    		start = System.currentTimeMillis();
    		SVM_DATA all = new SVM_DATA();
			ObjectInputStream all_object = new ObjectInputStream(new FileInputStream(detection_parameters.all)); 
			all.cls = (Classifier) all_object.readObject();
			all_object.close();
			LineNumberReader all_file = new LineNumberReader(new FileReader(detection_parameters.all_normalization));
			int all_size = Integer.parseInt(parser.getLineParameter (all_file, "\n", 0)); 
			all.mean = parser.Get_Data (all_size, all_file);
			all.deviation = parser.Get_Data (all_size, all_file); 
			all_file.close(); 
    		svm_classifiers.add(all);
    		Util.Compute_Processing_Time (start, "All SVM java");
    		
    		
   		} catch (IOException e1) {
			System.err.println("Failed to open svm trainning or normalization files");
			e1.printStackTrace();
		}	
		catch(ClassNotFoundException e2) {
			System.err.println("Failed to open svm trainning or normalization files");
			e2.printStackTrace();
		}
	}
	
	
	
}
