#ifndef __RELATEDPLUGIN_H_2004_06_23
#define __RELATEDPLUGIN_H_2004_06_23


#include <QObject>

// NPlugin
#include <searchplugin.h>
#include <scoreplugin.h>
#include <debtagsplugincontainer.h>
#include <scorecalculationstrategybase.h>

class QMainWindow;

class RelatedInput;
class RelatedFeedbackWidget;


namespace NPlugin
{

/** @brief A plugin offering a search for packages similar to another one and
  * providing a scoring based on the degree of similarity.
  *
  * The plugin offers to search packages similar to another package. The latter 
  * can be selected in a combobox. Additionally the degree of the maximum distance
  * to the package can be choosen. The distance is calculated by
  * \f$|(A \cup B) \setminus (A \cap B)|\f$
  *
  * The scores for the packages are calculated in the getScores() function.  
  */
class RelatedPlugin : public SearchPlugin, public ScorePlugin
{
	Q_OBJECT
	
	/** Class used to calculate the scores for related plugins. */
	class ScoreCalculator : public ScoreCalculationStrategyBase {
	public:
		/** @brief Holds the scores for the packages in the search result. */
		map<string, float> _scores;
		/** @brief Calculates the scores for the handed set of packages.
		*
		* Old calculations will be cleared.
		*/
		virtual void calculateScore(const set<string>& packages);
	};
	
	

	typedef std::string Tag;
public:
	static const QString PLUGIN_NAME;
	RelatedPlugin(const DebtagsPluginContainer& container);
	~RelatedPlugin();
	/** @name Plugin Interface
	  * 
	  * Implementation of the PluginInterface
	  */
	//@{
	virtual void init(IProvider* pProvider);
	/// @todo not yet implemented
	virtual void setEnabled(bool)	{};
	/// @todo not yet implemented
	virtual void setVisible(bool)	{};
	virtual QString name() const { return PLUGIN_NAME; }
	virtual QString title() const;
	virtual QString briefDescription() const;
	virtual QString description() const;
	//@}
	/** @name SearchPlugin interface
	  * 
	  * Implementation of the SearchPlugin interface
	  */
	//@{
	virtual uint searchPriority() const	{ return 10; }
	/** @brief Returns a widget where you can select the debtags you want to in- and exclude. */
	virtual QWidget* inputWidget() const;
	/** @brief Returns &quot;Debtags&quot;.  */
	virtual QString inputWidgetTitle() const;
	virtual QWidget* shortInputAndFeedbackWidget() const;
	virtual void clearSearch();
	virtual bool usesFilterTechnique() const	{ return false; };
	virtual const std::set<string>& searchResult() const;
	/** @brief Unused, because this plugin does not use the filter technique. */
	virtual bool filterPackage(const string&) const	{ return true; };
	virtual bool isInactive() const	{ return _isInactive; };
	//@}
	
	/** @name ScorePlugin interface
	  * 
	  * Implementation of the ScorePlugin interface
	  */
	//@{
	/** @brief Returns the score for the handed packages for the currently active search.
	  *
	  * The score for a package is calculated based on the distance of the tag sets of the
	  * package to the "base" package. The higher the distance, the lower
	  * the scores.
	  */
	virtual map<string, float> getScore(const set<string>& packages) const;
	/** @brief Returns true if a valid package was selected.
	  *
	  * It returns false if either no or an unkown package was selected.
	  */
	virtual bool offersScore() const;
	//@}




protected Q_SLOTS:
	/** @brief Called whenever the user requests to clear the search. */
	void onClearSearch()	{ clearSearch(); };
	/** @brief This is called everytime the search changes.
	  *
	  * It might emit the searchChanged() signal. */
	void evaluateSearch();
	/** @brief This is called whenever the text of the widget where to insert the 
	  * package to be matched changes. 
	  *
	  * Is only needed because the QComboBox::setCurrentText("") function does not 
	  * trigger a activated() signal.
	  */
	void onInputTextChanged(const QString& text);
	/** This enables/ disables the visible widgets. */
	void setWidgetsEnabled(bool enabled);
private:
	/** Used to calculate the scores fo the plugin. */
	mutable ScoreCalculator _calculator;
	/** The container which holds this plugin. */
	const DebtagsPluginContainer& _container;
	/** @brief Holds the result of the search currently active. */
	std::set<string> _searchResult;
	/** @brief Holds a pointer to the Plugin Manager which manages this plugin. */
	IProvider* _pProvider;
	/** @brief Holds a pointer to the main window this plugin belongs to. */
	QMainWindow* _pMainWindow;
	/** @brief Holds a pointer to the widget used for inputting the related search. */
	RelatedInput* _pRelatedInput;
	/** @brief Holds a pointer to the widget used for displaying the currenly active search.
	  *
	  * This widget will be hidden if no search was active i.e. if #_isInactive is true. */
	RelatedFeedbackWidget* _pRelatedFeedbackWidget;
	/** This holds if the search is currently inactive. */
	bool _isInactive;
	/** This is the delay time in ms the delay timer waits for another input. */
	uint _delayTime;
};


}	// namespace NPlugin

#endif //	__RELATEDPLUGIN_H_2004_06_23

