/*
    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"
#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>

namespace clustering
{
	namespace cbc
	{
		std::string Config::cluto_exe = "/home/boban/software/cluto-2.1.2/Linux-x86_64/scluster";
		std::string Config::dir = "/home/boban/cic/zabrac/";
		std::string Config::matrix_name = "kipi_knigi_rzepa_substAdjP_AmISubj_Coord_NGen_pq";
		std::string Config::kbest_file = "/home/boban/cic/zabrac/kipi_knigi_rzepa_subst_AdjP_AmISubj_Coord_NGen_rwf_cut_0.01.sims";
		std::string Config::workdir = "/mnt/big/cbc/";
		size_t Config::k = 20;
		double Config::theta1 = 0.2;
		double Config::theta2 = 0.12;
		double Config::sigma = 0.1;
		double Config::not_similiar_threshold = 0.20;
		size_t Config::simmatrix_top_x=20000;
		size_t Config::phase_3_top_x=200;
		std::string Config::committee_output_file = "./out";
		std::string Config::committee_output_suffix = "_rwf_cut0_01";
		size_t Config::committee_min_tf = 200;
		size_t Config::committee_min_nz = 10;
		double Config::committee_sum_tf_threshold = 0;
		std::string Config::clmethod = "agglo";
		std::string Config::crfun = "i2";
		REMOVE_FEATURES Config::remove_features = NORMAL;
		bool Config::verbose = false;
		bool Config::cluto_verbose = false;
		bool Config::intermediate = false;
		bool Config::cluto_intermediate = false;
		std::string Config::cluto_file;

		Options::Options(int argc, char**argv)
		{
			ParseOptions(argc, argv);
		}

		void Options::ParseOptions(int argc, char**argv)
		{
			using namespace boost::program_options;
			using namespace std;

			string config_file, type;
			options_description options(120);
			options_description basic("Cbc options", 120);
			options_description outOptions("Output options", 120);

			basic.add_options()
					("help", "Prints this text")
					("config-file", value<string>(& config_file)->default_value("cbc.cfg"), "Config file path")
					("cluto-path", value<string>(& Config::cluto_exe), "Path to scluster executable file")
					("matrix-dir", value<string>(& Config::dir), "Path to supermaatrix dir")
					("matrix-name", value<string>(& Config::matrix_name), "Name of the supermatrix")
					("kbest-file", value<string>(& Config::kbest_file), "Path to k-best file")
					("workdir", value<string>(& Config::workdir), "Path to workdir")
					("k", value<size_t>(& Config::k), "K-best for clustering")
					("theta1", value<double>(& Config::theta1), "Theta 1")
					("theta2", value<double>(& Config::theta2), "Theta 2")
					("sigma", value<double>(& Config::sigma), "Sigma")
					("not-similar-threshold", value<double>(& Config::not_similiar_threshold), "Not similar threshold")
					("simmatrix-top-x", value<size_t>(& Config::simmatrix_top_x), "Sim matrix top x")
					("phase3-top-x", value<size_t>(& Config::phase_3_top_x), "Phase 3 top x")
					("committee-output-file", value<string>(& Config::committee_output_file), "Committee output file path")
					("committee-min-tf", value<size_t>(& Config::committee_min_tf), "Committee min tf")
					("committee-min-nz", value<size_t>(& Config::committee_min_nz), "Committee min nz")
					("committee-sum-tf-threshold", value<double>(& Config::committee_sum_tf_threshold), "Committee sum tf threshold")
					("clmethod", value<string>(& Config::clmethod), "Clmethod")
					("crfun", value<string>(& Config::crfun), "Crfun")
					("remove-features", value<string>(& type), "Removing features type")
					("cluto-file", value<string>(& Config::cluto_file), "Path to cluto output file")
					;

			outOptions.add_options()
					("verbose", "Produce lots of output for cbc")
					("cluto-verbose", "Produce lots of output for cluto")
					("intermediate", "Produce intermediate output for cbc")
					("cluto-intermediate", "Save cluto intermediate results")
					;

			options.add(basic).add(outOptions);

			variables_map vm;
			store(parse_command_line(argc, argv, options), vm);
			notify(vm);

			if (vm.count("help"))
			{
				std::cout << "CBC (Clustering by committee) application\n" << options << std::endl;
				exit(0);
			}

			if (vm.count("config-file"))
			{
				ifstream cfgfile( config_file.c_str() );
				if(cfgfile)
				{
					store(parse_config_file(cfgfile, basic), vm);
					notify(vm);
				}
				else
					cerr << "Cannot open config file " << config_file << ". Proceeding with defaults...\n";
			}
			Config::verbose = vm.count("verbose");
			Config::cluto_verbose = vm.count("cluto-verbose");
			Config::intermediate = vm.count("intermediate");
			Config::cluto_intermediate = vm.count("cluto-intermediate");
			SetRemoveFeaturesType(type);
			//add required parameters checking (defaulf values?)
		}

		void Options::SetRemoveFeaturesType(const std::string &type)
		{
			std::string lower_type = type;
			boost::algorithm::to_lower(lower_type);
			if(lower_type == "normal")
				Config::remove_features = NORMAL;
			else
			{
				if(lower_type == "min")
					Config::remove_features = MIN;
				else
				{
					if(lower_type == "weighted")
						Config::remove_features = WEIGHTED;
					else
						throw std::runtime_error("Unknown remove features type: " + type);
				}
			}
		}

	}//namespace cbc

}//namespace clustering

