/*
    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"
#define CFG_NO_LOOP "no-loop"
#define CFG_NO_XML "no-xml"
#define CFG_SORT_RESULTS "sort-results"


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::string WBSTOptions::GetOutDir() const
{
	return m_sOutDir;
}

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


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

bool WBSTOptions::GetNoLoop() const
{
	return noLoop;
}

bool WBSTOptions::GetNoXML() const
{
	return noXML;
}

bool WBSTOptions::GetSortResults() const
{
	return sortResults;
}

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);
	}
	CheckMatrices();
	CheckFunctions();
	boost::filesystem::create_directory( m_sOutDir );
}

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")
			(CFG_NO_LOOP, "Whether function should be computed for all tests, or 1 by 1")
			(CFG_NO_XML, "Whether XML file for each test should be saved to disk")
			(CFG_SORT_RESULTS, "Should results in .csv file be sorted or not")
			;
	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_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";
	if(m_VarMap.count(CFG_SORT_RESULTS))
		sortResults=true;
	else
		sortResults=false;
	if(m_VarMap.count(CFG_NO_LOOP))
		noLoop=true;
	else
		noLoop=false;
	if(m_VarMap.count(CFG_NO_XML))
		noXML=true;
	else
		noXML=false;
}
