/*
    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.
*/

#ifndef ARCH2_CONFIG_H
#define ARCH2_CONFIG_H
#include "arch_headers.h"
#include "LexicalUnit.h"
#include "SimpleWord.h"
#include "MEParser/MEParser.h"
#include "MEParser/ResourcesHolder.h"


//For parallel
struct OperatorAndLex
{
	int operatorIndex;
	LexicalUnits::LexicalUnitPtr ptr;
};

struct Triplet_OperatorFlexLex
{
	std::string flex;

	int operatorIndex;

	int nextIndex;
};

namespace me_architect
{
	typedef boost::shared_ptr<JOSKIPI::Operators::CCondition> CondPtr;

	class Options;

	class Config
	{
	public:

		std::string m_sWorkdir;
		std::vector<std::string> m_sCorpusFiles;
		std::vector<std::string> documents;
		std::vector<LexicalUnits::LexicalUnitPtr> m_vLexicalUnits;
		std::vector<size_t> rowLU;// indices in lexicalUnits
		std::vector<size_t> columnLU;// indices in lexicalUnits
		std::vector<CondPtr> m_vConditions; //operators for columns
		std::map<size_t, std::string> columnToFlex;
		std::map<size_t, std::string> rowToFlex;
		bool m_bFilterDisamb;
		std::string dictWithWords;
		std::string tempDictDir;
		size_t query_size;

		//Dictionary
		size_t min_tf;
		std::vector<std::string> stoplistFiles;
		std::vector<std::string> charStoplistFiles;
		std::set<Corpus::TFlexClass> flexes;
		bool dictOnly;


		std::string m_sMatrixName;
		std::string m_sCorpusInfo;
		bool removeAmbInterp;
		bool favorGers;


		/**
		  * Function going through words and their flex classes, returning words with proper
		  * flex class
		  * \param dictFromFile Dictionary loaded from file
		  * \param flex Chosen flex class
		  * \param out Output vector with words with chosen flex class
		  */
		void LoadSimpleWordsForColumns(std::vector<std::pair<std::string,std::string> > dictFromFile, std::string& flex,
									   std::vector<LexicalUnits::LexicalUnitPtr>&out);
		/**
						  * Function run on slave nodes. Loads row units and selected column operators
						  * \param ac Input arguments count
						  * \param av Input arguments
						  * \param columnRangeMin Number of first column operator to be loaded
						  * \param columnRangeMax Number of last (minus 1) column operator to be loaded
						  * \returns Config ready to start computing corpus
						  */
		static Config* Initalize(int ac, char*av[],int columnRangeMin,int columnRangeMax,int *shuffleTable);

		/**
						  * Function run on master node. Loads row units to create results matrix ready for data
						  * \param ac Input arguments count
						  * \param av Input arguments
						  * \returns Total number of column operators
						  */
		static std::vector<Triplet_OperatorFlexLex*> InitalizeForMasterNode(int ac, char *av[]);

		/**
						  * Function loading basic options from config files
						  * \param ac Input arguments count
						  * \param av Input arguments
						  */
		static void init(int ac, char *av[]);
		/**
						  * \returns Current instance of Config
						  */
		static Config* GetInstance();
		/**
						  * Cleans current instance of Config
						  */
		static void Delete();
		/**
						  * \returns Vector of operators and size they occupy in matrix
						  */
		std::vector<std::pair<std::string,size_t> > GetOperators_Columns();
		/**
						  * \returns Number of operators to be computed on each node
						  */
		int GetOperatorsPerNode();

	private:
		static Config* m_pInstance;
		/**
						  * Constructor setting basic options
						  */
		Config();


		/**
						  * Function loading column operators' names and their size in matrix
						  * \returns Total number of column operators
						  */
		std::vector<Triplet_OperatorFlexLex*> NumOfOperators();

		/**
						  * Function loading all lines from a file to a vector
						  * \param filename Name of file to load
						  * \param vec Target vector for loading lines from file
						  */
		void LoadStringVectror(const std::string &filename, std::vector<std::string> &vec);

		/**
						  * Function loading multiword lexical units for rows from files given in config
						  */
		void LoadRowME();

		/**
						  * Function loading signel word lexical units for rows from files given in config
						  */
		void LoadRowUnits();



		/**
						  * Function loading column operators within given range
						  * \param columnRangeMin Number of first column operator to be loaded
						  * \param columnRangeMax Number of last (minus 1) column operator to be loaded
						  */
		void LoadOperators(int columnRangeMin,int columnRangeMax,int *shuffleTable);

		/**
						  * Function loading whole file to single string
						  * \param filename File to be loaded
						  * \returns String with whole file loaded in it
						  */
		std::string LoadSingleOperatorString(const std::string& filename);

		/**
						  * Function loading words from file to a lexical units vector
						  * \param filename File to be read
						  * \param flex Flex class for tags
						  * \param out Lexical units vector for loaded words
						  */
		void LoadSimpleWords(const std::string &filename, std::string& flex,
							 std::vector<LexicalUnits::LexicalUnitPtr>&out);

		/**
						  * Function loading multiword lexical units for column operators from file
						  * \param filename File to be read
						  * \param out Target vector for loading operators
						  */
		void LoadMEForColumns(const std::string &filename, std::vector<LexicalUnits::LexicalUnitPtr> &out);

		/**
						  * Function parsing string for flex classes in it
						  * \param string String for parsing
						  * \returns Mask for flex class (1 or more)
						  */
		Corpus::TFlexClass GetFlexClass(const std::string&);



		int operatorsPerNode;

		std::vector<std::pair<std::string,size_t> > operators_columns;
		/**
			Format for normal units: op.file#words file#flex
			Format for ME: op.file#units file
			*/
		std::vector<std::string> m_vOperatorsME;
		std::vector<std::string> m_vOperatorsSimple;
		/**
			Format for normal units: words file#flex
			*/

		std::vector<std::string> m_vRowUnits;
		std::vector<std::string> m_vRowTermFiles;
		bool m_bChceckDocuments;
		boost::shared_ptr<JOSKIPI::Parsers::CAntlrParser> m_OperatorParser;



		friend class Options;

	};
}//namespace architect
#endif //ARCH2_CONFIG_H

