/*
 * settings_reader.cpp
 *
 *  Created on: 19.11.2011
 *      Author: isvoboda
 */

#include "settings_reader.hpp"

using namespace ppd;

//Dataset settings
#define DatasetStr "Dataset"
#define CLASS "class"
#define PATH_IMG_SETS "path_image_sets"
#define DATA_LIST "data_list_file"
#define PATH_ANN "path_annotations"
#define PATH_IMG "path_images"

//Type of descriptor
#define DESCRIPTOR "descriptor"

//VOC settings
#define VOCStr "VOC"
#define DESCR "descriptors"
#define VOC "vocabulary"
#define VOC_SIZE "voc_size"
#define BOW_FEATURES "bow_features"

//BOW settings
#define BOW "BOW"
#define BOW_fg "bow_fg_features"
#define BOW_bg "bow_bg_features"

//Training classifier settings
#define SVM_TRAINING "SVM_Training"
#define SVM_TYPE "SVM_type"
#define SVM_C "C"
#define C_GRID "C_grid"
#define SVM_KERNEL "SVM_kernel"
#define KERNEL_TYPE "type"
#define KERNEL_PARAMS "kernel_params"
#define KERNEL_GAMMA "gamma"
#define KERNEL_GAMMA_GRID "gamma_grid"
#define SVM_NU "SVM_nu"

//Classifier
#define CLASSIFIER "Classifier"
#define SVM_file "SVM_file"
#define SVM_name "SVM_name"
#define SVM_SCALING_PARAMETERS "scale_parameters"

//Detector
#define DETECTOR "Detector"
#define SCAN_ROW_STEP "scan_row_step"
#define SCAN_COL_STEP "scan_col_step"
#define DETECTION_WINDOW "detection_window"
#define SCAN_WINDOW_X "min_x"
#define SCAN_WINDOW_Y "min_y"
#define SCAN_WINDOW_SCALE_FACTOR "scale_factor"
#define SCAN_WINDOW_MIN_NEIGBOURS "min_neigbours"




SettingsReader::SettingsReader()
{
	this->initialize();
}

SettingsReader::SettingsReader(const std::string file_name)
{
	this->initialize();
	this->file_name = file_name;
}

void SettingsReader::initialize()
{
	file_name = "";
	type = 1;					//-1 - negative; 0 - occlusion; 1 - positive
	classType = "";				//Class type
	path_img_sets = "";			//path to file defining the images names and the flag of occurrence of specific class
	data_list = "";		//File defining names of files - images
	path_ann = "";		//Path to folder with annotations
	path_img = "";		//Path to folder with images
	descriptor_file = "";
	voc_file = "";
	bow_features_file = "";
	voc_size = 1000;
	svm_type = "";
	svm_kernel_type = "";
	svm_kernel_rbf_param_gamma = 0.;
	svm_nu = 0.;
	svm_c = 0.;

	gamma_grid = CvSVM::get_default_grid(CvSVM::GAMMA);
	c_grid = CvSVM::get_default_grid(CvSVM::C);

	bow_fg_file = "";
	bow_fg = "";
	bow_bg_file = "";
	bow_bg = "";

	svm_name = "";
	svm_file = "";

	svm_scaling_parameters = "";

	descriptor = this->SURF;

	scan_row_step = 1;
	scan_col_step = 1;

	detector_window_x = 100;
	detector_window_y = 100;
	detector_window_scale_factor = 1.5f;
	detector_min_neigbours = 25;
}

void SettingsReader::SetSettingsFile(const std::string file_name)
{
	this->file_name = file_name;
}

void SettingsReader::Read()
{
	try
	{
		ticpp::Document settings_file(this->file_name);
		settings_file.LoadFile();

		ticpp::Iterator<ticpp::Element> valueElem;
		ticpp::Iterator<ticpp::Element> categoryElem;
// The value of this child identifies the name of this element
		std::string strName;
		std::string strValue;

		for(categoryElem = categoryElem.begin(settings_file.FirstChildElement()); categoryElem != categoryElem.end(); categoryElem++)
		{
			categoryElem->GetValue(&strName);
			if(strName.compare(DatasetStr) == 0)
			{
//Dataset properties
				for(valueElem = valueElem.begin(dynamic_cast<ticpp::Node*>(&(*categoryElem))); valueElem != valueElem.end(); valueElem++)
				{
					valueElem->GetValue(&strName);
					if(strName.compare(CLASS) == 0)
					{
						this->classType = valueElem->GetText();
					}
					else if(strName.compare(PATH_IMG_SETS) == 0)
					{
						this->path_img_sets = valueElem->GetText();
					}
					else if(strName.compare(DATA_LIST) == 0)
					{
						this->data_list = valueElem->GetText();
					}
					else if(strName.compare(PATH_ANN) == 0)
					{
						this->path_ann = valueElem->GetText();
					}
					else if(strName.compare(PATH_IMG) == 0)
					{
						this->path_img = valueElem->GetText();
					}
				}
			}

//Vocabulary, descriptor etc properties
			else if(strName.compare(VOCStr) == 0)
			{
				for(valueElem = valueElem.begin(dynamic_cast<ticpp::Node*>(&(*categoryElem))); valueElem != valueElem.end(); valueElem++)
				{
					valueElem->GetValue(&strName);
					if(strName.compare(DESCRIPTOR) == 0)
					{
						int dscr = 0;
						valueElem->GetText(&dscr);
						this->descriptor = static_cast<Descriptor>(dscr);
					}
					else if(strName.compare(DESCR) == 0)
					{
						this->descriptor_file = valueElem->GetText();
					}
					else if(strName.compare(VOC) == 0)
					{
						this->voc_file = valueElem->GetText();
					}
					else if(strName.compare(VOC_SIZE) == 0)
					{
						int val;
						valueElem->GetText(&val);
						this->voc_size = val;
					}
					else if(strName.compare(BOW_FEATURES) == 0)
					{
						this->bow_features_file = valueElem->GetText();
					}
				}

			}

//BOW_features, names
			else if(strName.compare(BOW) == 0)
			{
				for(valueElem = valueElem.begin(dynamic_cast<ticpp::Node*>(&(*categoryElem))); valueElem != valueElem.end(); valueElem++)
				{
					valueElem->GetValue(&strName);
					if(strName.compare(BOW_fg) == 0)
					{
						this->bow_fg = strName;
						this->bow_fg_file = valueElem->GetText();
					}
					else if(strName.compare(BOW_bg) == 0)
					{
						this->bow_bg = strName;
						this->bow_bg_file = valueElem->GetText();
					}
				}

			}

//Classifier Training Parameters
			else if(strName.compare(SVM_TRAINING) == 0)
			{
				for(valueElem = valueElem.begin(dynamic_cast<ticpp::Node*>(&(*categoryElem))); valueElem != valueElem.end(); valueElem++)
				{
					valueElem->GetValue(&strName);
					if(strName.compare(SVM_TYPE) == 0)
					{}
					else if(strName.compare(SVM_C) == 0)
					{
						double val;
						valueElem->GetText(&val);
						this->svm_c = val;
					}
					else if(strName.compare(C_GRID) == 0)
					{
						double val;
						valueElem->GetAttribute("min", &val, false);
						this->c_grid.min_val = val;
						valueElem->GetAttribute("max", &val, false);
						this->c_grid.max_val = val;
						valueElem->GetAttribute("step", &val, false);
						this->c_grid.step = val;
					}
					else if(strName.compare(SVM_KERNEL) == 0)
					{
//Kernel Properties - type
						ticpp::Iterator<ticpp::Element> kernelProperties;
						for(kernelProperties = kernelProperties.begin(dynamic_cast<ticpp::Node*>(&(*valueElem))); kernelProperties != kernelProperties.end(); kernelProperties++)
						{
							kernelProperties->GetValue(&strName);
							if(strName.compare(KERNEL_TYPE) == 0)
							{
								this->svm_kernel_type = kernelProperties->GetText();
							}
							else if(strName.compare(KERNEL_PARAMS) == 0)
							{
//Kernel Params - gamma etc
								ticpp::Iterator<ticpp::Element> kernelParams;
								for(kernelParams = kernelParams.begin(dynamic_cast<ticpp::Node*>(&(*kernelProperties))); kernelParams != kernelParams.end(); kernelParams++)
								{
									kernelParams->GetValue(&strName);
									if(strName.compare(KERNEL_GAMMA) == 0)
									{
										double val;
										kernelParams->GetText(&val);
										this->svm_kernel_rbf_param_gamma = val;
									}
									else if(strName.compare(KERNEL_GAMMA_GRID) == 0)
									{
										double val;
										kernelParams->GetAttribute("min", &val, false);
										this->gamma_grid.min_val = val;
										kernelParams->GetAttribute("max", &val, false);
										this->gamma_grid.max_val = val;
										kernelParams->GetAttribute("step", &val, false);
										this->gamma_grid.step = val;
									}
								}
							}
						}
					}
					else if(strName.compare(SVM_NU) == 0)
					{
						double val;
						valueElem->GetText(&val);
						this->svm_nu = val;
					}

				}
			}

//Classifier file name
			else if(strName.compare(CLASSIFIER) == 0)
			{
				for(valueElem = valueElem.begin(dynamic_cast<ticpp::Node*>(&(*categoryElem))); valueElem != valueElem.end(); valueElem++)
				{
					valueElem->GetValue(&strName);
					if(strName.compare(SVM_file) == 0)
					{
						this->svm_file = valueElem->GetText();
					}
					else if(strName.compare(SVM_name) == 0)
					{
						this->svm_name = valueElem->GetText();
					}
					else if(strName.compare(SVM_SCALING_PARAMETERS) == 0)
					{
						this->svm_scaling_parameters = valueElem->GetText();
					}
				}
			}
//Detector properties
			else if(strName.compare(DETECTOR) == 0)
			{
				for(valueElem = valueElem.begin(dynamic_cast<ticpp::Node*>(&(*categoryElem))); valueElem != valueElem.end(); valueElem++)
				{
					valueElem->GetValue(&strName);
					if(strName.compare(SCAN_ROW_STEP) == 0)
					{
						double val;
						valueElem->GetText(&val);
						this->scan_row_step = val;
					}
					else if(strName.compare(SCAN_COL_STEP) == 0)
					{
						double val;
						valueElem->GetText(&val);
						this->scan_col_step = val;
					}
					else if(strName.compare(DETECTION_WINDOW) == 0)
					{
	//Detector scan window params - size
						ticpp::Iterator<ticpp::Element> DWindowParams;
						for(DWindowParams = DWindowParams.begin(dynamic_cast<ticpp::Node*>(&(*valueElem))); DWindowParams != DWindowParams.end(); DWindowParams++)
						{
							DWindowParams->GetValue(&strName);
							if(strName.compare(SCAN_WINDOW_X) == 0)
							{
								int val;
								DWindowParams->GetText(&val);
								this->detector_window_x = val;
							}
							else if(strName.compare(SCAN_WINDOW_Y) == 0)
							{
								int val;
								DWindowParams->GetText(&val);
								this->detector_window_y = val;
							}
							else if(strName.compare(SCAN_WINDOW_SCALE_FACTOR) == 0)
							{
								float val;
								DWindowParams->GetText(&val);
								this->detector_window_scale_factor = val;
							}
							else if(strName.compare(SCAN_WINDOW_MIN_NEIGBOURS) == 0)
							{
								int val;
								DWindowParams->GetText(&val);
								this->detector_min_neigbours = val;
							}
						}
					}
				}
			}
		}
	}
	catch (ticpp::Exception &e)
	{
		std::cerr << e.what() << std::endl;
	}
}


void SettingsReader::Read(const std::string file_name)
{
	this->file_name = file_name;
	this->Read();
}

std::string SettingsReader::get_class() const
{
	return this->classType;
}

std::string SettingsReader::get_path_img_sets() const
{
	return this->path_img_sets;
}

std::string SettingsReader::get_data_list_file() const
{
	return this->data_list;
}

std::string SettingsReader::get_path_ann() const
{
	return this->path_ann;
}

std::string SettingsReader::get_path_img() const
{
	return this->path_img;
}

SettingsReader::Descriptor SettingsReader::get_descriptor_type() const
{
	return this->descriptor;
}

std::string SettingsReader::get_descriptor_file_name() const
{
	return this->descriptor_file;
}

std::string SettingsReader::get_voc_file_name() const
{
	return this->voc_file;
}

std::string SettingsReader::get_bow_features_file_name() const
{
	return this->bow_features_file;
}

std::string SettingsReader::get_svm_type() const
{
	return this->svm_type;
}

std::string SettingsReader::get_svm_kernel_type() const
{
	return this->svm_kernel_type;
}

double SettingsReader::get_svm_kernel_rbf_param_gamma() const
{
	return this->svm_kernel_rbf_param_gamma;
}

double SettingsReader::get_svm_nu() const
{
	return this->svm_nu;
}

std::string SettingsReader::get_svm_file_name() const
{
	return this->svm_file;
}

std::string SettingsReader::get_svm_name() const
{
	return this->svm_name;
}

std::string SettingsReader::get_svm_sacle_parameters() const
{
	return this->svm_scaling_parameters;
}

CvParamGrid SettingsReader::get_svm_gamma_grid() const
{
	return this->gamma_grid;
}

CvParamGrid SettingsReader::get_svm_c_grid() const
{
	return this->c_grid;
}

std::string SettingsReader::get_bow_fg() const
{
	return this->bow_fg;
}

std::string SettingsReader::get_bow_fg_name() const
{
	return this->bow_fg_file;
}

std::string SettingsReader::get_bow_bg_name() const
{
	return this->bow_bg_file;
}

std::string SettingsReader::get_bow_bg() const
{
	return this->bow_bg;
}

unsigned int SettingsReader::get_voc_size() const
{
	return this->voc_size;
}

unsigned int SettingsReader::get_scan_row_step()
{
	return this->scan_row_step;
}

unsigned int SettingsReader::get_scan_col_step()
{
	return this->scan_col_step;
}

unsigned int SettingsReader::get_detector_window_x()
{
	return this->detector_window_x;
}

unsigned int SettingsReader::get_detector_window_y()
{
	return this->detector_window_y;
}

float SettingsReader::get_detector_scan_factor()
{
	return this->detector_window_scale_factor;
}

unsigned int SettingsReader::get_detector_min_neigbours()
{
	return this->detector_min_neigbours;
}

void SettingsReader::PrintSettings()
{
	std::cout << "----- Data set properties -----" << std::endl;
	std::cout << "Class: " << this->classType << std::endl;
	std::cout << "Data list: " << this->data_list << std::endl;
	std::cout << "Path img sets: " << this->path_img_sets << std::endl;
	std::cout << "Path ann: " << this->path_ann << std::endl;
	std::cout << "Path img: " << this->path_img << std::endl;
	std::cout << std::endl;

	std::cout << "----- VOC properties -----" << std::endl;
	std::cout << "Descriptors filename: " << this->descriptor_file << std::endl;
	std::cout << "Vocabulary filename: " << this->voc_file << std::endl;
	std::cout << "VOC size: " << this->voc_size << std::endl;
	std::cout << "BOW features filename: " << this->bow_features_file << std::endl;
	std::cout << std::endl;

	std::cout << "----- BOW properties -----" << std::endl;
	std::cout << "BOW fg name: " << this->bow_fg << std::endl;
	std::cout << "BOW bg name: " << this->bow_bg << std::endl;
	std::cout << std::endl;

	std::cout << "----- Training classifier properties -----" << std::endl;
	std::cout << "SVM type: " << this->svm_type << std::endl;
	std::cout << "Kernel type: " << this->svm_kernel_type << std::endl;
	std::cout << "Kernel gamma: " << this->svm_kernel_rbf_param_gamma << std::endl;
	std::cout << "SVM nu: " << this->svm_nu << std::endl;
	std::cout << std::endl;

	std::cout << "----- Classifier -----" << std::endl;
	std::cout << "SVM filename: " << this->svm_file << std::endl;
	std::cout << "SVM name: " << this->svm_name << std::endl;
	std::cout << "SVM scale parameters: " << this->svm_scaling_parameters << std::endl;
	std::cout << std::endl;

	std::cout << "----- Detector properties -----" << std::endl;
	std::cout << "Scan row step: " << this->scan_row_step << std::endl;
	std::cout << "Scan col step: " << this->scan_col_step << std::endl;
	std::cout << "Detection Window min x: " << this->detector_window_x << std::endl;
	std::cout << "Detection Window min y: " << this->detector_window_y << std::endl;
	std::cout << "Detection Window Scale Factor: " << this->detector_window_scale_factor << std::endl;
	std::cout << "Min Neigbours to satisfy detection: " << this->detector_min_neigbours << std::endl;
	std::cout << std::endl;
}
