//
// C++ Implementation: debtagshelper
//
// Description: 
//
//
// Author: Benjamin Mesing <bensmail@gmx.net>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include "debtagshelper.h"

#include <xapian.h>

#include <helpers.h>

#include <ept/debtags/vocabulary.h>

#include <algorithm>


namespace NUtil
{

std::set<string> tagsForPackage(const string& package, const Xapian::Database& xapian) 
{
	std::set<string> result;
	std::pair<bool, Xapian::Document> document = documentForPackage(package, xapian);
	if (!document.first) 
	{
		return result;
	}
	Xapian::Document& doc = document.second;
	for (Xapian::TermIterator it = doc.termlist_begin(); it != doc.termlist_end(); ++it) 
	{
		// if the term is a tag
		if ((*it).find("XT")==0) 
		{
			result.insert((*it).erase(0,2));
		}
	}
	return result;
}


/** @brief A Xapian ExpandDecider which accepts only tags. */
class AcceptTags : public Xapian::ExpandDecider 
{
	virtual bool operator()(const std::string& term) const
	{
		return (term[0] == 'X') && (term[1] == 'T');
	}


};

std::set<string> companionTags(const std::set<string>& tags, const Xapian::Database& xapian) 
{
	using namespace Xapian;
	std::set<string> result;
	if (tags.empty()) 
	{
		// Dismiss all tags which have no accociated document (i.e. package)
		for (TermIterator it = xapian.allterms_begin("XT"); it != xapian.allterms_end("XT"); ++it) 
		{
 			if (xapian.term_exists(*it))
				result.insert((*it).substr(2, string::npos));
		}
		cout << result.size() << endl;
		return result;
	}
	set<string> terms;
	for (set<string>::const_iterator it = tags.begin(); it != tags.end(); ++it)
	{
		terms.insert(string("XT")+*it);
	}
	Xapian::Query query(Xapian::Query::OP_AND, terms.begin(), terms.end());
	Xapian::Enquire enq(xapian);
	enq.set_query(query);
	
	AcceptTags decider;
	// get all results
	Xapian::MSet mset = enq.get_mset(0, xapian.get_doccount());
	Xapian::RSet allDocuments;
	for (Xapian::MSetIterator it = mset.begin(); it != mset.end(); ++it)
		allDocuments.add_document(*it);
	
	// assuming a maximum of 1000000 tags in the vocabulary
	Xapian::ESet companions = enq.get_eset(1000000, allDocuments, &decider);
	cout << companions.size() << endl;
	for (ESetIterator it = companions.begin(); it != companions.end(); ++it)
		result.insert((*it).substr(2, string::npos));
	return result;
}

}	// namespace NUtil

