/*
    Copyright (C) 2012 Bartosz Broda, Jacek Bochenek, Łukasz Biłeńkij, 
    Damian Jaworski, Wojciech Mazur, Dominik Piasecki, Maciej Piasecki, 
    Radosław Ramocki
    
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option)
any later version.

    This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. 

    See the LICENSE and COPYING files for more details.
*/

#include "config.h"
#define CFG_HELP "help"
#define CFG_CONFIG_FILE "cfg-file"
#define CFG_WINDOW_MATRIX_PATH "window-matrix"
#define CFG_MATRIX_WEIGHTER_PATH "matrix-weighter-path"
#define CFG_WORKDIR "workdir"
#define CFG_BASE_FUNCTION "weight-simfunction"
#define CFG_SVD_RUNNER_PATH "svd-runner-path"
#define CFG_SVD_PATH "svd-path"
#define CFG_SVD_DIMENSIONS "svd-dimensions"
#define CFG_SVD_ITERATIONS "svd-iterations"
#define CFG_SM2ST_PATH "sm2st-path"
#define CFG_AFTER_SVD_FUNCTION "simfunction-after-svd"
#define CFG_PARALLEL_SIM_PATH "parallel-sim-path"
#define CFG_MPI_HOSTFILE "mpi-hostfile"
#define CFG_MPI_NODES "mpi-nodes"
#define CFG_HISTOGRAM_PATH "histogram-path"
#define CFG_HISTOGRAM_VALUE "histogram-value"
#define CFG_MEAN_MEDIAN_PATH "median-path"
#define CFG_TXT2SM_PATH "txt2sm-path"

Config* Config::instance=NULL;



void Config::init(int ac,char**av)
{
	if(instance==NULL)
		instance = new Config();
	instance->initOptions(ac,av);
}

Config* Config::getInstance()
{

	return instance;
}
void Config::Delete()
{
	if(instance)
	{
		delete instance;
		instance = NULL;
	}
}

void Config::initOptions(int ac,char**av)
{
	namespace po= boost::program_options;
	std::string configfile;

	po::options_description cmdline("Command line only options", 100);
	po::options_description basic("Basic options", 100);

	cmdline.add_options()
			(CFG_HELP, "Prints this message")
			(CFG_CONFIG_FILE, po::value<std::string>(&configfile), "Config file")

			;
	basic.add_options()
			(CFG_WINDOW_MATRIX_PATH, po::value<std::string>(& windowMatrixPath), "Path for window matrix to be processed")
			(CFG_MATRIX_WEIGHTER_PATH, po::value<std::string>(& matrixWeighterPath), "Path for binary of matrix weighter")
			(CFG_WORKDIR, po::value<std::string> (& workdir), "Path for temporary files")
			(CFG_BASE_FUNCTION, po::value<std::string> (& baseFunction)->default_value("LogEnt()"), "Similarity function for initial weighting")
			(CFG_SVD_RUNNER_PATH, po::value<std::string> (& svdRunnerPath), "Path for binary of svd runner")
			(CFG_SVD_PATH, po::value<std::string> (& svdPath), "Path for binary of SVDLIBC's svd")
			(CFG_SVD_DIMENSIONS, po::value<int> (& svdRunnerDimensions), "Number of desired dimensions after svd reduction")
			(CFG_SVD_ITERATIONS, po::value<int> (& svdRunnerIterations), "Number of iterations step for svd")
			(CFG_SM2ST_PATH, po::value<std::string> (& sm2stPath), "Path for sm2st binary")
			(CFG_TXT2SM_PATH, po::value<std::string> (& txt2smPath), "Path for txt2sm binary")
			(CFG_AFTER_SVD_FUNCTION, po::value<std::string> (& afterSVDFunction)->default_value("cos()"), "Similarity function to be used on svd's results")
			(CFG_PARALLEL_SIM_PATH, po::value<std::string> (& parallelSimPath), "Path for binary of parallel similarity")
			(CFG_MPI_HOSTFILE, po::value<std::string>(& hostFile), "Hostfile for mpirun")
			(CFG_MPI_NODES, po::value<int>(& nodeNum)->default_value(2), "Number of nodes in parallel environment")
			(CFG_HISTOGRAM_PATH, po::value<std::string>(& histogramPath), "Path for histogram binary")
			(CFG_HISTOGRAM_VALUE, po::value<std::vector<double> >(& histogramValues), "Values for histograms' steps")
			(CFG_MEAN_MEDIAN_PATH, po::value<std::string> (& meanMedianPath), "Path for mean median binary")
			;

	po::variables_map vm;
	po::options_description all("",100);

	all.add(cmdline).add(basic);

	po::store(po::parse_command_line(ac, av, all), vm);
	po::notify(vm);

	if( vm.count(CFG_HELP) )
	{
		std::cout << "SVD total runner by Damian Jaworski, 150019@student.pwr.wroc.pl\n";
		std::cout << all << std::endl;
		exit(0);
	}
	std::ifstream cfgfile( configfile.c_str() );

	if(cfgfile)
	{
		po::store(po::parse_config_file(cfgfile, basic), vm);
		po::notify(vm);
	}
	else if( vm.count(CFG_CONFIG_FILE) )
		throw std::runtime_error("Cannot open config file\n");
	if(workdir[workdir.length()-1]!='/')
		workdir = workdir+"/";

}
