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

#include "ppd.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
#include <fstream>
#include <string>

void store_libsvm_format_data(cv::Mat& fg, cv::Mat& bg, std::string& file_name)
{
	std::fstream output_file;
	output_file.open(file_name.c_str(), std::fstream::out);
	if(output_file.is_open())
	{
		for(int i = 0; i < fg.rows; i++)
		{
			output_file << 1 << " ";
			for(int j = 0; j < fg.cols; j++)
			{
				// indexing from 1 in libsvm: j+1
				output_file << j+1 << ":" << fg.at<float>(i,j) << " ";
			}
			output_file << std::endl;
		}

		for(int i = 0; i < bg.rows; i++)
		{
			output_file << -1 << " ";
			for(int j = 0; j < bg.cols; j++)
			{
				output_file << j+1 << ":" << bg.at<float>(i,j) << " ";
			}
			output_file << std::endl;
		}

		output_file.close();
	}
	else
		std::cerr << "Failed to open file: " << file_name << std::endl;
}

int main(int argc, char* argv[])
{
	//Missing settings file
	if(argc < 2)
			return -1;

	ppd::SettingsReader options_fg = ppd::SettingsReader(argv[1]);
	ppd::SettingsReader options_bg = ppd::SettingsReader(argv[2]);
	ppd::DataSetReader reader_fg, reader_bg;
	ppd::BOW bow_extractor;
	ppd::Extractor extractor;
	cv::Ptr<cv::DescriptorMatcher> dmatcher = cv::DescriptorMatcher::create("BruteForce");

	ppd::ExtractorManager extractorManager;

	options_fg.Read();
	
	reader_fg.work_fg();
	reader_fg.set_properties(options_fg);
	reader_fg.initialize();
	
	options_bg.Read();
	
	reader_bg.work_bg();
	reader_bg.set_properties(options_bg);
	reader_bg.initialize();

	cv::Mat voc;
	ppd::read_voc(options_fg.get_voc_file_name(), voc);
	dmatcher->add(std::vector<cv::Mat>(1, voc));
	bow_extractor.set_DescriptorMatcher(dmatcher);

	switch (options_fg.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 fg_bow_features, bg_bow_features;
	extractorManager.extract_data(reader_fg, extractor, bow_extractor, fg_bow_features);
	extractorManager.extract_data(reader_bg, extractor ,bow_extractor, bg_bow_features);

	if(argc > 3)
	{
		std::string file_name = std::string(argv[3]);
		store_libsvm_format_data(fg_bow_features, bg_bow_features, file_name);
	}
	else
	{
		cv::FileStorage fs(options_fg.get_bow_fg_name(), cv::FileStorage::WRITE);
		fs << options_fg.get_bow_fg().c_str();
		fs << "[";
		fs << fg_bow_features;
		fs << "]";
		fs.release();
	
		fs = cv::FileStorage(options_bg.get_bow_bg_name(), cv::FileStorage::WRITE);
		fs << options_bg.get_bow_bg().c_str();
		fs << "[";
		fs << bg_bow_features;
		fs << "]";
		fs.release();
	}

	return 0;
}
