/*
 * main.cpp
 *
 *  Created on: 6.3.2011
 *      Author: isvoboda
 */

#include "ppd.hpp"
#include <iostream>

//#ifdef __WIN32__
//
//#else
//
//#endif

using namespace ppd;

int main(int argc, char* argv[])
{
	if(argc < 2)
		return -1;
//Reading settings file
	SettingsReader settingsReader(argv[1]);
	settingsReader.Read();
	//Reading DataSet properties
	DataSetReader reader;
	reader.set_properties(settingsReader);
	try
	{
		reader.initialize();
	}
	catch(Exception *e)
	{
		std::cout << e->get() << std::endl;
		delete e;
	}

	ppd::Extractor extractor;
	ppd::ExtractorManager extractorManager;
	extractorManager.set_resolution(640, 480);
	cv::Mat voc;
	ppd::read_voc(settingsReader.get_voc_file_name(), voc);

	cv::Ptr<cv::DescriptorMatcher> dmatcher = cv::DescriptorMatcher::create("BruteForce");
	dmatcher->add(std::vector<cv::Mat>(1, voc));
	ppd::BOW bow_extractor(dmatcher);

//	ppd::BOW bow_extractor;
	switch (settingsReader.get_descriptor_type())
	{
		case ppd::SettingsReader::SIFT:
			extractor = ppd::Extractor(cv::FeatureDetector::create("SIFT"), cv::DescriptorExtractor::create("SIFT"));
			break;
		case ppd::SettingsReader::SURF:
			extractor = ppd::Extractor(cv::FeatureDetector::create("SURF"), cv::DescriptorExtractor::create("SURF"));
			break;
		case ppd::SettingsReader::SIFT_COLOR:
			extractor = ppd::Extractor(cv::FeatureDetector::create("SIFT"), cv::DescriptorExtractor::create("OpponentSIFT"));
			break;
		case ppd::SettingsReader::SURF_COLOR:
			extractor = ppd::Extractor(cv::FeatureDetector::create("SURF"), cv::DescriptorExtractor::create("OpponentSURF"));
			break;
		default:
			extractor = ppd::Extractor(cv::FeatureDetector::create("SURF"), cv::DescriptorExtractor::create("SURF"));
			break;
	}

	cv::Mat descriptor;
	cv::Mat scaled_descriptor;
	ppd::SVM classifier;
	ppd::Scaler scaler;

//	classifier.load_classifier(settingsReader.get_svm_file_name(), settingsReader.get_svm_name());
	classifier.load_model(settingsReader.get_svm_file_name());

	float lower, upper;
	std::vector<float> min_f, max_f;
	scaler.read_scale_parameters(settingsReader.get_svm_sacle_parameters(), lower, upper, min_f, max_f );

	int class_val = 0;
	float result_tmp = 0.;
//	float result = 0.;
	int trueClass, falseClass, trueClassPredicted, falseClassPredicted , total, notComputed;
	trueClass = falseClass = trueClassPredicted = falseClassPredicted = total = notComputed = 0;

	#pragma omp parallel for schedule(dynamic) private(result_tmp, class_val)
	for(unsigned int i = 0; i < reader.get_number_of_objects(); i++)
	{
		class_val = reader.get_class(i);
		if(class_val == 0)
		{
			continue;
		}

		//If the image is too large, resize it to 640x480
		cv::Mat image = reader[i];

		if(class_val == 1)
		{
			const ppd::Object* object = reader.get(i);
			cv::Rect_<int> mask = (static_cast<const BoundedObject*>(object)->get_bounding_box());
			extractorManager.extract_data(image, extractor, bow_extractor, descriptor, &mask);
		}
		else
			extractorManager.extract_data(image, extractor, bow_extractor, descriptor);

		if(descriptor.data == NULL)
			continue;
		try
		{
//			result = classifier.predict(descriptor);
			scaler.scale(descriptor, scaled_descriptor, lower, upper, min_f, max_f);
			result_tmp = classifier.predict(scaled_descriptor);
		}
		catch(cv::Exception& e)
		{
			#pragma omp critical(errorexception)
			std::cerr << "Processing file: " << reader.get_file_name(i) << " " << e.msg << std::endl;
			continue;
		}
		#pragma omp critical(evaluation)
		{
			std::cout<< "File: "<< reader.get_file_name(i) << " " << class_val << " ; " << result_tmp << std::endl;
		}

	}

	return 1;
}
