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

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

#include <time.h>
#include <unistd.h>
#include <sys/time.h>

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

using namespace ppd;

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		std::cerr << "Not enough parameters." << std::endl;
		return -1;
	}
//-------------------- Reading settings file -----------------------------------
	SettingsReader settingsReader(argv[1]);
	settingsReader.Read();

	settingsReader.PrintSettings();

//	cv::Mat image = cv::imread(argv[2],-1);
//	if(image.empty())
//	{
//		std::cerr << "Failed to load the image: " << argv[2] << std::endl;
//		return -1;
//	}

//------------------------------- Reading DataSet ------------------------------
	DataSetReader reader;
	reader.set_properties(settingsReader);
	try	{reader.initialize();}
	catch (Exception *e){std::cout << e->get() << std::endl; delete e;}
//	reader.work_fg();

//------------------ Setting BoW properties ready for detection -----------------
	cv::Mat voc;
	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));

	Extractor 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;
	}

	BOW bow_extractor = BOW(dmatcher);

//--------------------------- SVM propertis ------------------------------------
	ppd::SVM classifier;
	try{ classifier.load_model(settingsReader.get_svm_file_name());}
	catch(ppd::Exception *ex){ std::cerr << ex->get() << std::endl; delete ex; return -1; }

	ppd::Scaler scaler;
	try{ scaler.read_scale_parameters(settingsReader.get_svm_sacle_parameters()); }
	catch(ppd::Exception *ex){ std::cerr << ex->get() << std::endl; delete ex; return -1; }

//--------------------------- Detector properties ------------------------------

	ppd::Detector detector = ppd::Detector(settingsReader.get_scan_row_step(),
			settingsReader.get_scan_col_step());
	cv::Size_<int> min_scan_window(settingsReader.get_detector_window_x(),
			settingsReader.get_detector_window_y());
	detector.set_scan_windows(min_scan_window,
			settingsReader.get_detector_scan_factor());

	std::vector<Response> positions;
	std::vector<Response> responses;

//--------------------------- Detection procedure ------------------------------

	for (unsigned int i = 0; i < reader.get_number_of_objects(); i++)
	{

		std::cerr << i << "/" << reader.get_number_of_objects() << std::endl;

		std::string img_name = reader.get_file_name(i);
		std::string img_id = img_name;
		std::stringstream sstream;


		cv::Mat img = reader[i];
		detector.detect(img, extractor, bow_extractor, classifier, scaler, positions, responses, settingsReader.get_detector_min_neigbours());

		img_id.erase(img_name.length() - 4);

		cv::Mat response_image = cv::Mat::zeros(img.rows, img.cols, CV_8UC1);

		int scale = 1;
		for(size_t i = 1; i < responses.size(); i++)
		{
			int j = i-1;

			response_image.at<unsigned char>(static_cast<int>(responses[j].position.y+responses[j].position.height/2.f), static_cast<int>(responses[j].position.x + responses[j].position.width/2.f)) = static_cast<unsigned char>(responses[j].response * 255);

			if(responses[j].position.height != responses[i].position.height)
			{
				sstream << img_id << "_response_" << scale << ".jpg";
				cv::imwrite(sstream.str(), response_image);
				sstream.clear();
				response_image = cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
				scale++;
			}
		}
		sstream << img_id << "_response_" << scale << ".jpg";
		cv::imwrite(sstream.str(), response_image);
		sstream.clear();


		//Drawing detections
		for (size_t j = 0; j < positions.size(); j++)
		{
			cv::Point_<int> lu = cv::Point_<int>(positions[j].position.x , positions[j].position.y);
			cv::Point_<int> rd = cv::Point_<int>(positions[j].position.x + positions[j].position.width,positions[j].position.y + positions[j].position.height);
			cv::rectangle(img, lu, rd, cv::Scalar_<int>(255, 0, 0), 1);
			std::cout << img_id << " " << positions[j].response << " " << positions[j].position.x + 1 << " " << positions[j].position.y + 1 << " "	<< positions[j].position.x + 1 + positions[j].position.width << " " << positions[j].position.y + 1 + positions[j].position.height << std::endl;
		}
		cv::imwrite(img_name, img);
		positions.clear();
		responses.clear();
	}

	return 0;
}
