/*
    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_CBC_H
#define CLUSTERING_CBC_H
#include "kbest.h"
#include "clutowrapper.h"

namespace clustering
{
	namespace cbc
	{
		struct WordSimPair
		{
			std::string word;
			double sim;
			bool operator< (const WordSimPair &wsp)
			{
				return word < wsp.word;
			}
		};
		struct wsp_sim_cmp
		{
			bool operator()(const WordSimPair &wsp1, const WordSimPair &wsp2) const
			{
				return wsp1.sim > wsp2.sim;
			}
		};


		class CBC
		{
		public:
			CBC(bool only_phase_3 = false);
			void StartCBC();
			void ResumePhase3(std::string & prev_phase_filename);
		private:
			bool m_bUseTScoreRank;
			Matrices::SymmetricSimMatrixPtr m_pSimMatrix;
			Matrices::SuperMatrixPtr m_pMatrix;
			KBestPtr m_pKBest;
			smartcomparator::compare::CompareFunctionPtr m_pCmp;
			ClustersPtr m_pClusters;//L
			
			typedef std::pair< Matrices::CompressedVectorPtr, std::set<std::string> > Committee;
			typedef std::vector<Committee > Committees; // v[ centroid, cluster ]
			Committees m_Committees;
			std::map<std::string, std::set<size_t> > m_mWordToCommitteeIndex;
			std::map<size_t, std::set<WordSimPair, wsp_sim_cmp> > m_mCommitteeIndexToWord;

			void Phase2();
			void Phase3();
			void WriteResults();
			void WriteCommitteesToWords();
			void WriteWordsToCommmittees();
			void SaveClutoFile();
			void CreateOutputFilename();

			/**
			 *
			 * \param out queue of Committees for word w, contains pointers to elemetsn of m_Committees, so 
			 * memory is managed by m_Committees
			 */
			void PrepareCommitteesForWord(std::multimap<double,std::pair<Committee*, size_t>, std::greater<double> > &out, const std::string &word);
			void RecalculateSimilariteis(std::multimap<double,std::pair<Committee*, size_t>, std::greater<double> > &sims, const std::string &word);
			bool IsSimilar(Committee* c, std::vector<Committee*> &all);
			void RemoveOverlapingFeatures(Matrices::CompressedVectorPtr word_vector_copy, Matrices::CompressedVectorPtr c);

			Matrices::CompressedVectorPtr CountAvg( std::set<std::string> &cluster);
			void WeightCentroid( Matrices::CompressedVectorPtr pCentroid);
			double SimCentroid(Matrices::CompressedVectorPtr &v1, Matrices::CompressedVectorPtr &v2);

			void WriteCommittees(Committees &committees, size_t iter_no);

			std::vector<double> m_vSumCols;
			void CountFeaturesSums();

			double m_dN;

		};//class cbc
	}//namespace cbc
}//namespace clustering

#endif //CLUSTERING_CBC_H

