/*
    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 CLUSTERING_CLUTOWRAPPER
#define CLUSTERING_CLUTOWRAPPER
#include "matrices_all.h"
#include "comparator_all.h"
#include "kbest.h"

namespace clustering
{
	namespace cbc
	{
		typedef std::pair<double, std::set<std::string> > ScoredClusterPair;
		typedef std::multimap<double, std::set<std::string> > Clusters;
		typedef boost::shared_ptr<Clusters> ClustersPtr;

		class ClutoWrapper
		{
		public:
			ClutoWrapper(Matrices::SuperMatrixPtr pMatrix, smartcomparator::compare::CompareFunctionPtr pCmp, 
					KBestPtr pKBest, Matrices::SymmetricSimMatrixPtr pSimMatrix);
			void StartClustering(const std::vector<std::string> & wordsToCluster, std::string outdir, size_t k);
			ClustersPtr GetClusters();
		private:
			typedef std::map<int, std::vector<int> > ClusterTree;
			std::set<std::string> m_WordsToCluster;
			std::vector<std::string> m_CurrentKBest;

			ClustersPtr m_pOutClusters;

			void Initalize();

			void PrepareCurrentWords(const std::vector<std::string> &words);
			void PrepareCurrentKBest(const std::string &word);
			void ClusterOne(const std::string &word);
			size_t WriteSubMatrix(const std::string &word);
			void RunCLUTO(const std::string &word, size_t size);
			void ReadCLUTOOutput(const std::string &word);
			void PrintTree(size_t root_id, ClusterTree& clusters, size_t level, const std::string &word );
			void SelectBestOne(const std::string &word);
			void GetChildren(int root, ClusterTree &clusters, std::vector<int> &leafs);
			double ScoreCluster(int cluster, ClusterTree &clusters, const std::string &words);

			ClusterTree m_CurrentCluster;
			std::string m_sOutDir;
			/// (max) size of kbest
			size_t m_stK;
			// common things:
			Matrices::SuperMatrixPtr m_pMatrix;
			Matrices::SymmetricSimMatrixPtr m_pSimMatrix;
			smartcomparator::compare::CompareFunctionPtr m_pCmp;
			KBestPtr m_pKBest;

			// cluto params:
			std::string m_sClutoExe;
			std::string m_sClMethod;
			std::string m_sCrFun;

		};
	}//namespace cbc
}//namespace clustering
#endif //CLUSTERING_CLUTOWRAPPER
