/*
    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_ROCK_ROCKHEAPS_H
#define CLUSTERING_ROCK_ROCKHEAPS_H

#include "../base/Cluster.h"

namespace clustering
{
	namespace ROCK
	{
		struct DecrasingDoubleCmp
		{
			bool operator()(double d1, double d2) const
			{
				return d1 > d2;
			}
		};//DecrasingDoubleCmp

		/**
		Struktura bedaca elementem w lokalnych kopcach - zawiera grupe i jej miare
		jakosci w stosunku do grupy dla ktorej dany kopiec jest zbudowany.
		Struktura tez jest funktorem do porownywania w strict-weak-ordering malejaco
		po jakosci.
		*/
		struct ClusterWithGoodness
		{
			ClusterWithGoodness() : dGoodness(0)
			{
			}

			ClusterWithGoodness(ClusteringBase::ClusterPtr pC, double dG)
				: pCluster(pC),
				dGoodness(dG)
			{
			}

			ClusteringBase::ClusterPtr pCluster;
			double dGoodness;
		};//ClusterWithGoodness


		typedef std::multimap<double, ClusteringBase::ClusterPtr, DecrasingDoubleCmp> GoodnessMap;

		class GoodnessHeap
		{
		public:
			/**
			 Jako, ze dana grupa moze miec tylko jedna najlepsza wartosc (dla lokalnego kopca) 
			 i (dla globalnego kopca) dla jednej grupy moze byc tylko jeden najlepszy, to
			 nie ma sensu rozdzielac operacji update/add.
			*/
			void AddOrUpdateElement(ClusteringBase::ClusterPtr cluster, double goodness);
			void RemoveElement(ClusteringBase::ClusterPtr cluster);
			ClusterWithGoodness GetMaxElement();
			ClusterWithGoodness PopMaxElement();
			std::set<size_t>& GetAllClusterIndices();

			size_t Size();
		private:
			GoodnessMap m_HeapData;
			std::map<size_t, double> m_GoodnessIndex;
			std::set<size_t> m_AllClusters;
			
		};//GoodnessHeap

	}// namespace ROCK
}// namespace Clustering
#endif //CLUSTERING_ROCK_ROCKHEAPS_H

