/*
    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 "wbst_headers.h"
#include "options.h"

#define CFG_HELP "help"
#define CFG_VERSION "version"
#define CFG_CONFIG_FILE "config-file"

#define CFG_WBST_FILES "wbst"
#define CFG_MATRICES "matrices"
#define CFG_FUNCTIONS "sim"
#define CFG_THREAD_COUNT "threads"
#define CFG_OUT_DIR "outdir"
#define CFG_FLEX_CLASS "flex"
#define CFG_LOAD_CCS "load-ccs"

namespace wbst
{
	namespace po = boost::program_options;

	WBSTOptions::WBSTOptions(int argc, char *argv[])
	{
		InitalizeOptions(argc, argv);
		ParseOptions();
	}
	std::vector< std::string > & WBSTOptions::GetFunctions()
	{
		return m_vFunctions;
	}

	const std::string & WBSTOptions::GetFlexClass() const
	{
		return m_sFlexClass;
	}

	std::vector< std::pair<std::string, std::string> >& WBSTOptions::GetPathToMatrixVector()
	{
		return m_vPathToMatrix;
	}
	std::vector< std::vector<WBSTQuestion> > & WBSTOptions::GetQuestions()
	{
		return m_vQuestions;
	}
	std::string WBSTOptions::GetOutDir() const
	{
		return m_sOutDir;
	}

	std::vector<std::string>  WBSTOptions::GetWBSTFiles()
	{
		return m_vWBSTFiles;
	}

	size_t WBSTOptions::GetNumberOfThreads() const
	{
		return m_cThreads;
	}

	bool WBSTOptions::GetLoadCCS() const
	{
		return m_bLoadCCS;
	}

	void WBSTOptions::ParseOptions()
	{
		std::cout << "WBST Tester by Bartosz Broda (bartosz.broda@pwr.wroc.pl)\n";
		if(m_VarMap.count(CFG_HELP) )
		{
			std::cout << m_Options << std::endl;
			exit(-1);
		}

		if(m_VarMap.count(CFG_VERSION) )
		{
			std::cout << "Version " << VERSION << std::endl;
			exit(-1);
		}
		LoadWBSTFiles();
		CheckMatrices();
		CheckFunctions();
		boost::filesystem::create_directory( m_sOutDir );
	}

	void WBSTOptions::LoadWBSTFiles()
	{
		for(size_t i = 0; i < m_vWBSTFiles.size(); i++)
		{
			std::string &filename = m_vWBSTFiles[i];
			std::ifstream file(filename.c_str() );
			if(!file)
				throw std::runtime_error( "Cannot open wbst file: " + filename);
			std::string line;
			std::getline(file, line);//first line is only a header
			m_vQuestions.push_back( std::vector<WBSTQuestion>() );
			std::vector<WBSTQuestion> &questions = m_vQuestions[i];

			while(std::getline(file,line) )
			{
				boost::trim(line);
				if(line.length() == 0 )
					continue;
				WBSTQuestion q(line);
				questions.push_back( q );
			}
		}
	}

	void WBSTOptions::CheckMatrices()
	{
		for(size_t i = 0; i < m_vMatricesPaths.size(); i++)
		{
			std::string &str = m_vMatricesPaths[i];
			char last_char = str[ str.length() -1 ];
			if(last_char == '\\' || last_char == '/')
				str = str.substr(0, str.length() -1 );
			boost::filesystem::path p(str);
			p.normalize();
			std::string matrix_name = p.filename().c_str();
			std::string matrix_dir = p.branch_path().string();
			std::cout << "Checking matrix " << matrix_name << " in " << matrix_dir << "...";
			Matrices::IO::CheckSuperMatrixFiles( matrix_dir, matrix_name );
			std::cout << " OK!\n";
			m_vPathToMatrix.push_back( std::pair<std::string, std::string>(matrix_dir, matrix_name));
		}
	}

	void WBSTOptions::CheckFunctions()
	{
		//TODO checking of functions
	}

	void WBSTOptions::InitalizeOptions(int argc, char *argv[])
	{
		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_VERSION, "Prints version number.")
			(CFG_CONFIG_FILE, po::value<std::string>(&m_sConfigFile)->default_value(std::string("wbst.cfg")), "Config file")
			;
		basic.add_options()
			(CFG_WBST_FILES, po::value<std::vector<std::string> >(&m_vWBSTFiles), "Files with (E)WBST test.")
			(CFG_MATRICES, po::value<std::vector<std::string> >(&m_vMatricesPaths), "Directories with matrices.")
			(CFG_FUNCTIONS, po::value<std::vector<std::string> >(&m_vFunctions), "Similarity functions.")
			(CFG_THREAD_COUNT, po::value<size_t >(&m_cThreads)->default_value(1), "Number of threads.")
			(CFG_OUT_DIR, po::value<std::string>(&m_sOutDir)->default_value(std::string("./results")), "Output directory.")
			(CFG_FLEX_CLASS, po::value<std::string>(&m_sFlexClass)->default_value(std::string("subst")), "Flex class of a test")
			(CFG_LOAD_CCS, po::value<bool>(&m_bLoadCCS)->default_value(false), "Should load CCS part of matrices?")
			;

		po::options_description config("",100);
		config.add(basic);

		m_Options.add(cmdline).add(config);

		po::store(po::parse_command_line(argc, argv, m_Options), m_VarMap);
		po::notify(m_VarMap);

		std::ifstream cfgfile( m_sConfigFile.c_str() );

		if(cfgfile)
		{
			po::store(po::parse_config_file(cfgfile, config), m_VarMap);
			po::notify(m_VarMap);
		}
		else if( m_VarMap.count(CFG_CONFIG_FILE) && !m_VarMap.count(CFG_HELP) &&  ! m_VarMap.count(CFG_VERSION))
			std::cerr << "Cannot open config file " << m_sConfigFile << ". Proceeding with defaults...\n";
	}
}//namespace wbst


