/* This file is part of the KDE project
   Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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 GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include <math.h>

#include <kdirlister.h>

#include <qdir.h> 
#include <stdlib.h>
#include <ktempfile.h>

#include <kdebug.h>
#include <klocale.h>
#include <dcopclient.h>
#include <kcmdlineargs.h>
#include <kglobal.h>

#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <kstandarddirs.h>


#include <qfile.h>
#include <qfileinfo.h>
#include <kcmdlineargs.h>
#include <kpushbutton.h>

#include "kio/netaccess.h"
#include "kio_kwest.h"

#include <kwest_search_daemon_dcopiface_stub.h>
#include <kapplication.h>

#include <kconfigbase.h>
#include <kconfig.h>

#include <qtimer.h>
#include <kdesktopfile.h>
#include <kfileitem.h>

#include <math.h>
using namespace KIO;


static const KCmdLineOptions options[] =
{
	{ "+protocol", I18N_NOOP( "Protocol name" ), 0 },
	{ "+pool", I18N_NOOP( "Socket name" ), 0 },
	{ "+app", I18N_NOOP( "Socket name" ), 0 },
	KCmdLineLastOption
};

//FIXME:using KApplication but KInstance might be good enough ?

extern "C" 
{	int KDE_EXPORT kdemain( int argc, char **argv )
	{
		putenv(strdup("SESSION_MANAGER="));
		KCmdLineArgs::init(argc, argv, "kio_kwest", 0, 0, 0, 0);
		KCmdLineArgs::addCmdLineOptions( options );
		KApplication app( false, false );
		
		// BIG BUG PROBLEM HERE !We want to be anonymous even if we use DCOP
		//because dcop blocks my ioslave !!! :-( kapplication problem QTimer problem?
		//this means no communication with the config tools
		//and since the config are a kuniqueapplication 
		//the kprocess returns immediately because of a fork
		//so I can't know when the file is updated
		//I could use a kdirlister .
		
		KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
		KwestProtocol slave( args->arg(0), args->arg(1), args->arg(2) );
 		//QTimer::singleShot( 1*1*10, this, SLOT(indexFiles()));
		slave.dispatchLoop();
		return 0;
	}
}


KwestProtocol::KwestProtocol(const QCString &protocol,
                                 const QCString &pool, const QCString &app)
	: 	ForwardingSlaveBase(protocol, pool, app) ,
  		m_Redirected(0), m_rootUpdated(1) , m_fromListDir(0) , 
		m_fromStat(0), m_HighlightingsReceived(FALSE) , m_AllHitsAreHere(0),
		m_stored_queriesDir("")
				
{
	
	
	//init config and dirs
	m_stored_queriesDir = locateLocal("appdata","stored_queries");
	//FIXME:not here 
	QDir d(locateLocal("appdata",""));
	if (!d.exists())
		d.mkdir("stored_queries",TRUE);
	
	kdDebug() << "START KwestProtocol CALLED store in "  << m_stored_queriesDir<< endl;

	connect(&m_impl, SIGNAL(AllHitsAreHere()),
		 this, SLOT(processKwestHits() ));
	
	//TODO:when syntax highlighter returns 
	connect(&m_impl, SIGNAL(HighLightingsAreHere()),
		 this, SLOT(processKwestHighlightings()));
	
	//when everything is done (usefull if hits are not received all at the same time.
	connect(&m_impl, SIGNAL(HitsAreHere()),
		 this, SLOT(processKwestHits()));
	
	connect(this, SIGNAL(kwestFinished()),
		 this, SLOT(processCluceneFinished()));
	
	connect(&m_impl, SIGNAL(OutPutToGUI()),
		this, SLOT(processGUIOutput()));
	connect(&m_impl, SIGNAL(OutPutToConfig()),
		 this, SLOT(processConfigOutput()));
	
}

KwestProtocol::~KwestProtocol()
{
}

void KwestProtocol::stat(const KURL &url)
{
	kdDebug() << "KwestProtocol::stat: " << url << endl;
 
	//FIXME:don't forger the QUERY
	QString path = url.path();
	
	if ( path.isEmpty() || path == "/" )
	{
		kdDebug() << "KwestProtocol::stat: " << url << "ROOTING" << endl;
		KIO::UDSEntry entry;
		m_impl.createTopLevelEntry( entry );
		statEntry( entry );
		finished();
		//notify the world the directory content has changed: 
		//if (m_rootUpdated == 0)
		this->notifyRootDirChanged();		
		return;
	}
	
	else if (m_impl.isWantedURL(url , IOSLAVE_PROTOCOL_NAME_FULL BACKEND_BEAGLE) )
	{
	   redirection(IOSLAVE_PROTOCOL_NAME_FULL);
	   finished();
	   return;
	}
	else if (m_impl.isWantedURL(url , IOSLAVE_PROTOCOL_NAME_FULL BACKEND_CLUCENE) )
	{
	   redirection(IOSLAVE_PROTOCOL_NAME_FULL);
	   finished();
	   return;
	}
	
	else if (m_impl.isWantedURL(url , SEARCH_FORM_URL ))
	
	{
		kdDebug() << "KwestProtocol::stat: " << url << " SEARCH" << endl;
		
		//FIXME: help needed. 
		//I just want to redirect to clucene:/, but it seems I need to give stat some entry
		//so I tell stat THIS is a symlink or what ever inside clucene protocol. 
		//Then stat calls internal GET and GET receives the wanted error
		//that the url is a DIRECTORY. So GET stops. then my last redirection goes to the root.
		//is that not CRAZY: Please help.
		//I want to redirect to clucene:, because then I force a listdir on clucene:/
		
		KIO::UDSEntry entry;
		m_impl.createHTMLSearchFormEntry(entry);
		statEntry( entry);
		finished();
		return;
	}
	
	else if (m_impl.isWantedURL(url , BACKUP_URL ) )
	{
		kdDebug() << "KwestProtocol::stat: " << url << "BACKUP"  << endl;
		KIO::UDSEntry entry;
		m_impl.createBackup(entry);
		statEntry( entry );
// 		ForwardingSlaveBase::stat(url);
		finished();
		return;
	}
	
	else if (m_impl.isWantedURL(url , GUI_SEARCH_URL ) )
	{
		kdDebug() << "KwestProtocol::stat: " << url << "GUISEASRCH" << GUI_SEARCH_URL << endl;
		KIO::UDSEntry entry;
		m_impl.createGUISearchEntry(entry);
		statEntry( entry );
		finished();
		return;
	}
	
	else if (m_impl.isWantedURL(url , CONFIG_INDEXES_URL ) )
	{
		kdDebug() << "KwestProtocol::stat: " << url << "CONFIG" <<  CONFIG_INDEXES_URL<< endl;
		KIO::UDSEntry entry;
		m_impl.createConfigIndexesEntry(entry);
		statEntry( entry );
		finished();
		return;
	}
	
	else if (m_impl.isWantedURL(url , GO_HOME_URL ) )
	{
		kdDebug() << "KwestProtocol::stat: " << url << "GOHOME" << GO_HOME_URL << endl;
		KIO::UDSEntry entry;
		m_impl.createGoHomeEntry(entry);
		statEntry( entry );
		finished();
		return;
	}

	//do nothing with HTML_SEARCH_URL. It is a web page, we have nothing to do with.
/*	else if (m_impl.isWantedURL(url , HTML_SEARCH_URL ) )
	{
}*/
	
	else
	{
		//this might be a query, new or old
		
		kdDebug() << "KwestProtocol::stat: " << url << "NEW OLD QUERY BEING CHECKED"  << endl;

		KURL newURL = url;
		QString p = url.path() + url.query();
		if (!(p.startsWith("/")))
		{
			p= "/" + p;
			newURL.setPath(p);
			kdDebug() << "KwestProtocol::stat: redirection " << m_impl.query() << endl;
			kdDebug() << "KwestProtocol::stat: redirection " << newURL.url() << endl;
			redirection(newURL.url());
			finished();
			return;
		}
		
		// check if embedded query-name in url from a saved query
		//do redirection in listdir because kdeinit sends a late execute
		QStringList tmpList = QStringList::split("/ clQN:", p);
		if (tmpList.count()==2)
		{
			//found a name for the query 
			kdDebug() << "KwestProtocol::stat: FOUND A clQN NAME " <<  *tmpList.at(1) << endl;
			m_impl.m_queryName =  *tmpList.at(1);
		}
/*		//FIXME BUG MAKE IT ENGINE DEPENDANT
		else if ( p.startsWith("/beagle?query=") )
		{
			kdDebug() << "KwestProtocol::stat: DID NOT FOUND A clQN NAME " << endl;

			QString a =IOSLAVE_PROTOCOL_NAME_FULL"beagle?query=";
			//HACK multi replace
			QString toStoreName =  p.remove(0,13);
			toStoreName = toStoreName.remove(0,1);
			kdDebug() << "KwestProtocol::stat: NAME NOW WILL BE" << toStoreName << endl;

			//setups the name of the query to be eqal to the query-pattern itself
			m_impl.m_queryName = toStoreName;
		}
		else if ( p.startsWith("/lucene?query=") )
		{
			kdDebug() << "KwestProtocol::stat: DID NOT FOUND A clQN NAME " << endl;

			QString a =IOSLAVE_PROTOCOL_NAME_FULL"lucene?query=";
			//HACK multi replace
			QString toStoreName =  p.remove(0,13);
			toStoreName = toStoreName.remove(0,1);
			kdDebug() << "KwestProtocol::stat: NAME NOW WILL BE" << toStoreName << endl;

			//setups the name of the query to be eqal to the query-pattern itself
			m_impl.m_queryName = toStoreName;
		}*/
		else 
		{
			//FIXME: should not be done here since url is not what we want
			kdDebug() << "KwestProtocol::stat: DID NOT FOUND A clQN NAME and BAD QUERY" << endl;

			//HACK multi replace
			QString toStoreName = p.remove(0,1);
			kdDebug() << "KwestProtocol::stat: NAME NOW WILL BE" << toStoreName << endl;

			//setups the name of the query to be eqal to the query-pattern itself
			m_impl.m_queryName = toStoreName;
		}
		
		//cleanup url and setup query() query_url()
		m_impl.urlToPattern(newURL); //->m_query defined
		KIO::UDSEntry entry;
		//???????????????
		m_impl.createQueryEntry(entry , m_impl.query_url() ,m_impl.m_queryName  ,"folder_green" );
		statEntry(entry);
		finished();
	}
}

//code much modified from kio_locate.cpp
void KwestProtocol::listDir(const KURL &url)
{
	kdDebug() << "KwestProtocol::listDir:ENTERED " << url << endl;	
	kdDebug() << "KwestProtocol::listDir:ENTERED " << url.uriMode() << endl;


	m_impl.m_isAutoCompletion = FALSE;	
	
	if (url.url() == GO_HOME_URL)
	{
		kdDebug() << "KwestProtocol:listdir:GO_HOME_URL REDIRECTED " << url << endl;
		redirection(IOSLAVE_PROTOCOL_NAME_FULL);
		finished();
		return;
	}
	
	if (m_impl.isWantedURL(url , IOSLAVE_PROTOCOL_NAME_FULL BACKEND_BEAGLE) )
	{
	   redirection(IOSLAVE_PROTOCOL_NAME_FULL);
	   finished();
	   return;
	}
	
	if (m_impl.isWantedURL(url , IOSLAVE_PROTOCOL_NAME_FULL BACKEND_CLUCENE) )
	{
	   redirection(IOSLAVE_PROTOCOL_NAME_FULL);
	   finished();
	   return;
	}
	if (url.url() == BACKUP_URL)
	{
		kdDebug() << "KwestProtocol::listDir:BACKUP "  << endl;
		redirection(KURL(this->m_stored_queriesDir));
		finished();
		return;
	}
	
	if (url.url() == GUI_SEARCH_URL )
	{
		m_impl.m_kprocess ="";
		kdDebug() << "KwestProtocol:listdir:PROCESSING GUI STAT REDIRECTED" << url << endl;
//		QString myU = "clucene:/" + m_impl.query();
		//redirection(myU);
		m_impl.startGuiSearch();
		//KURL newUrl("clucene:/hello");
		//redirection(newUrl);
		//finished();
		return;
	}
	
	if (url.url() == CONFIG_INDEXES_URL)
	{
		m_impl.m_kprocess = "";
		kdDebug() << "KwestProtocol:listdir:PROCESSINGCONFIG_INDEXES_URL REDIRECTED " << url << endl;
		m_impl.startGuiConfig();
		return;
	}
	
	if (url.url() == SEARCH_FORM_URL)
	{
		kdDebug() << "KwestProtocol::listDir:SEARCH FORM REDIRECTION"  << endl;
		redirection(IOSLAVE_PROTOCOL_NAME_FULL);
		finished();
		return;
	}

	if ( url.path().isEmpty() )
	{
		redirection(IOSLAVE_PROTOCOL_NAME_FULL);
		finished();
		return;
	}
	
	//FIXME:is decoding ok ?
	if ( !url.path().startsWith("/") )
	{
		redirection(IOSLAVE_PROTOCOL_NAME_FULL+ url.path());
		finished();
		return;
	}
			
	//blackmagic or old code I forgot why it is here	
	if ( url.path().length() <= 1 )
	{
		kdDebug() << "KwestProtocol::listDir:      LISTROOT " << url << endl;
		listRoot();

		return;
	}
	
	else 
	{

		//Query-Pattern stored in m_query
		m_impl.urlToPattern(url);
		
		kdDebug() << "KwestProtocol::listDir query : " <<  m_impl.query()<<endl;

		// Whenever you enter a "/" in konquerors location box (and you have
		// autocompletion enabled), konqueror will call listDir for autocompletion.
		// In such cases we do nothing here, as autocompletion does not make
		// any sense for this protocol.
		if (m_impl.query().isEmpty() || m_impl.m_isAutoCompletion) 
		{
			kdDebug() << "KwestProtocol::listDir:QUERY IS EMPTY OR \
					AUTOCOLPLITION " << url << endl;
			finished();
			return;
		}
		
		// check if embedded query-name in url from a saved query
		QStringList tmpList = QStringList::split("/ clQN:", m_impl.query());
		 
		if (tmpList.count()==2)
		{
			kdDebug() << "KwestProtocol:: TMPLIST " << tmpList << endl;

			m_impl.setQuery((*tmpList.at(0)).stripWhiteSpace());
			redirection(IOSLAVE_PROTOCOL_NAME_FULL+m_impl.query());
				finished();
				kdDebug() << "KwestProtocol:: FILENAMEFILENAME " << m_impl.m_queryName << endl;
				kdDebug() << "KwestProtocol:: QUERY " << m_impl.query() << endl;
				return;
		}
		
		//strip white spaces
		QString testWhite(m_impl.query().stripWhiteSpace());
		kdDebug() << "KwestProtocol:: TESTWHITE -" << testWhite <<"-"<< endl;

		if (testWhite != m_impl.query())
		{
			m_impl.setQuery(testWhite);
			redirection(IOSLAVE_PROTOCOL_NAME_FULL+m_impl.query());
			finished();
			return;
		}
		
		if (    !testWhite.startsWith( SEARCH_AND_QUERY_FORM_URL)
		    && (!testWhite.startsWith( SEARCH_AND_QUERY_FORM_URL_CLUCENE))
		     && (!testWhite.startsWith( SEARCH_AND_QUERY_FORM_URL_BEAGLE))
		    )
		{
			m_impl.setQuery(SEARCH_AND_QUERY_FORM_URL + testWhite);
			KURL u;
			u.setProtocol("rekwest");
			//FIXME: mixing PATH an QUERY here ???
			u.setPath( m_impl.query() );
			kdDebug() << "KwestProtocol:: SEARCHQUERY -" << u.url() <<"-"<< endl;
			kdDebug() << "KwestProtocol:: SEARCHQUERY -" << u.path() <<"-"<< endl;
			kdDebug() << "KwestProtocol:: SEARCHQUERY -" << u.uriMode() <<"-"<< endl;
			redirection(u);
			finished();
			return;
		}
		else
		{
			//DO NOT remove the webform query protocol
			// let the search daemon decide what to do ?
// 			QString aStr = SEARCH_AND_QUERY_FORM_URL;
// 			m_impl.setQuery(m_impl.query().remove(0,aStr.length()) );
			kdDebug() << "KwestProtocol:: FINAL -" << m_impl.query() <<"-"<< endl;

			infoMessage(i18n("Searching for  %1 ...").arg(m_impl.query() ) );
			
			m_impl.addQueryToList();
			
			m_currentURL = url;
			int ok_startQuery = m_impl.startQuery();
			if (ok_startQuery < 1) 
			{
				error( KIO::ERR_UNSUPPORTED_ACTION, i18n( "Beagle daemon not running" ) );
				redirection(IOSLAVE_PROTOCOL_NAME_FULL);
				finished();

				return;
			}
		}
	}	
}

void KwestProtocol::listRoot()
{
	kdDebug() << "KwestProtocol::listRoot   ROOOOOOT   STAAARTED"  << endl;

	//should init the query list to tell the ioslacve the number of objects to draw
	
	KIO::UDSEntry entry;

	// create toplevel directory
	m_impl.createTopLevelEntry(entry);
	listEntry(entry, false);

	// create GUI-search Wizard entry
	m_impl.createGUISearchEntry(entry);
	listEntry(entry, false);

	//create all searches of the session
	KIO::UDSEntryList m_queryList;
	m_impl.listRoot( m_queryList );
	
	//totalSize(m_queryList .count()+4);
	
	KIO::UDSEntryListIterator it = m_queryList.begin();
	KIO::UDSEntryListIterator end = m_queryList.end();
	for(; it!=end; ++it)
	{
		listEntry(*it, false);
	}

	// create GUI-Index-Search Wizard entry
	m_impl.createConfigIndexesEntry(entry);
	listEntry(entry, false);
	
	// create link to webform search
	m_impl.createHTMLSearchEntry(entry);
	listEntry(entry, false);
	

	// create History Directory
	m_impl.createBackup(entry);
	listEntry(entry, false);
	
	entry.clear();
	listEntry(entry, true);
	
	kdDebug() << "KwestProtocol::listRoot  ROOOOT FINISHED "  << QString::number(m_rootUpdated) << endl;

	finished();
}

//code from ForwardingSlaveBase::copy kde 3.4
void KwestProtocol::copy(KURL src , KURL dest, int /*permissions*/, bool /*overwrite*/)
{
	kdDebug() << "KwestProtocol::copy: " << src << ", " << dest << endl;
 	error( KIO::ERR_UNSUPPORTED_ACTION, i18n( "Only linking is supported." ) );
	return;

/*	       KIO::Job *job = KIO::file_copy(src, dest, permissions,
                                    overwrite, false);
	       connectJob(job);
	       qApp->eventLoop()->enterLoop();*/
}

void KwestProtocol::prepareUDSEntry(KIO::UDSEntry & /*entry*/, bool   listing )
{
	//listing tell if happends during listdir. Here not.
	kdDebug() << "KwestProtocol::prepareUDSEntry: listing=="<< listing << endl;
// 	KFileItem item(entry);
}

void KwestProtocol::del(const KURL &url, bool /*isFile*/)
{
	kdDebug() << "GETXH. KwestProtocol::del: CALLED" << url << endl;
	error(KIO::ERR_UNSUPPORTED_ACTION,
	      i18n("Delete not implemented"));

}

//ok, so far I do most of all stuff in the listdir mode to allow integration with KFileDialog
//but with the option prefer HTML results, I could return in html immediately
void KwestProtocol::get(const KURL & url)
{
	
	kdDebug() << "KwestProtocol::get CALLED" << url << endl;

	if (url.hasHost())
	{
		error(KIO::ERR_UNSUPPORTED_ACTION,
		      i18n("You cannot specify a host with this protocol. "
				      "Please use the "+QString(IOSLAVE_PROTOCOL_NAME_FULL)+ " format instead."));
		return;
	}
	
	//TODO get a Statistic report
	else if ( (url.directory(0,0)  == m_impl.query_url().path()
			  && url.fileName(FALSE) == HTML_RESULTS_URL) )
	{
		//the ioslave should load the results, they will be stored on disk
		//if the citation query is not finished it should return a statistics only file
		 //should  store them on disk ?
		kdDebug() << "GETXH. YOU WANT TO READ the HTML RESULTS" << endl;
		
		 /*int doIt = */m_impl.displayHTMLResults();
		 //encode m_display according to doIt
		data(QByteArray());
		finished();
		return;
	}
	
	//force ::get to believe it is requesting a directory
	else
	{
		kdDebug() << "ERROR LOOP" << endl;
		error(KIO::ERR_IS_DIRECTORY, QString::null);
		return;
	}	
}

//target is the query-pattern
void KwestProtocol::createDesktopFile(const QString &   target)
{
	kdDebug() << "KwestProtocol::createDesktopFile target:" << target << endl;
	QString s = target;
	s = s.remove(0,1);
	s = s.remove(s.length()-1,1);
	//FIXME BUG here it should decide if beagle or other called !!!!
// 	QString targetURL 	= QString(IOSLAVE_PROTOCOL_NAME_FULL)+QString(SEARCH_AND_QUERY_FORM_URL) + s ;
QString targetURL 	=  + s ;
	
	KURL u(targetURL);
	kdDebug() << "KwestProtocol::createDesktopFile list str:" << u.url() << endl;

	int id = this->m_impl.m_query_urlList.findIndex(u.url());
	QString newTarget = *(m_impl.m_queryList.at(id));
	QString desktopFileName = m_stored_queriesDir  + "/" + newTarget + ".cl_search";

	kdDebug() << "KwestProtocol::createDesktopFile 2:" << desktopFileName << endl;

	
	KDesktopFile * d = new KDesktopFile(desktopFileName,FALSE);
	
	d->setGroup("Desktop Entry");
	d->writeEntry("Icon" , "kfind");
	d->writeEntry("Type" , "Link");
	d->writeEntry("URL" ,  targetURL + "/ clQN:" + newTarget );
	d->writeEntry("Indexes" , "unknown");
	d->sync();	
	delete d;	
}

//is this ForwardingSlaveBase ???????? Yes I guess since it is from a virtual function
void KwestProtocol::symlink( const QString &   target, const KURL &   dest, bool   /*overwrite*/)
{
	kdDebug() << "KwestProtocol::symlink: new target" << target<< endl;
	kdDebug() << "KwestProtocol::symlink:          dest" << dest << endl;
	
	createDesktopFile(target);
	finished();
	return;
	
} 

void KwestProtocol::mkdir(const KURL &/*url*/, int /*permissions*/)
{
	error( KIO::ERR_UNSUPPORTED_ACTION, i18n( "Only linking is supported." ) );
	return;
}	

// KIO::ForwardingSlaveBase::rewriteURL: Rewrite an url to it's forwarded counterpart
// I use ForwardingSlaveBase::stat(BACKUP_URL) 
bool KwestProtocol::rewriteURL(const KURL &url, KURL &newUrl)
{
   	kdDebug() << "KwestProtocol::rewriteURL:   "<< url.url() <<endl;
   	QString dir = locateLocal("appdata","stored_queries");
 	//Much help needed. useless but I need it. I don't know how to do. 
	//So I do has folloe. I use the rewriteURL call only to make sure the MKDIR call or the SYMLINK
	//call will be clucene-aware. Then I write myself the desktopfiles inside SYMLINK OR MKDIR
	QString newDest = dir + "/tmp.tmp";
	newUrl = KURL(newDest);
	kdDebug() << "KwestProtocol::rewriteURL:   "<<  newUrl <<endl;
	return true;
}

void KwestProtocol::notifyRootDirChanged()
{
	kdDebug() << "KwestProtocol::notifyRootDirChanged  UPTADE DRIN"  
			<< QString::number(m_rootUpdated) << endl;
	QByteArray params;
	QDataStream stream(params, IO_WriteOnly);
// 	DCOPClient *client=kapp->dcopClient();
	DCOPClient *client=this->dcopClient();
	stream << (KURL) KURL(IOSLAVE_PROTOCOL_NAME_FULL);
	client->send("*", "KDirNotify*", "FilesAdded(KURL)", params);
	m_rootUpdated=1;
}

void KwestProtocol::processKwestHits()
{
	kdDebug() << "KwestProtocol::processKwestHits() YOU ARE WRITTING ENTRYS" << endl;
	//FIXME: read from a QStringList so far but will use 
	///TODO: name display: first the ranking, then the filename, then the folder

	//dirlister
	//create a cache of kfileitems
	
	KFileItemList localItems;
						
	UDSEntry entry;
	
	QStringList results;
	m_impl.getResultsList(results);
 	UDSEntryList entries;
	int c = results.count();//FIXME:expensive???
	int nMax;
	if (c>0)
		nMax 	= (int) ((log10 ((double) c))+1);
	kdDebug() << "KwestProtocol::processKwestHits() ENTRYS are : " << c << endl;

	int count =0;
	//home entry
	m_impl.createGoHomeEntry(entry);
	//home item
	localItems.append(new KFileItem(entry,GO_HOME_URL, FALSE));
	
	entries +=  entry;

	QStringList::ConstIterator itDisplay    = m_impl.m_request.resultsDisplay.begin();
	QStringList::ConstIterator itMime    = m_impl.m_request.resultsMimeType.begin();
	QStringList::ConstIterator itModTime = m_impl.m_request.resultsModTime.begin();
	QStringList::ConstIterator itMode_T  = m_impl.m_request.resultsMode.begin();
	QStringList::ConstIterator itSize  = m_impl.m_request.resultsSize.begin();
	QStringList::ConstIterator itPixmap  = m_impl.m_request.resultsStoredPreview.begin();
// 	QStringList::ConstIterator itItem  = m_impl.m_request.resultsItem.begin();
	int chunk_counter = 0;
	QMap<QString, QStringList> map;

	for (QStringList::ConstIterator it = results.begin(); it != results.end(); ++it) 
	{
		chunk_counter++;
		kdDebug() << "KwestProtocol::processKwestHits result: " << *it << endl;  
		kdDebug() << "KwestProtocol::processKwestHits result: " << *itPixmap << endl;  
		++count;
		int n;
		n = (int) ((log10( (double) count) )+1 );
		QString zeroStr;
		zeroStr.fill( '0', nMax-n );

		//put everything into a QMap to avoid duplicates ?
		//or check for duplicates, but it is computer intensive or?
		//this allow to separate queries on metadata and full text and to mix both
		//when wanted.
		const QString name = zeroStr + QString::number(count) + "- " + (*itDisplay);
		QStringList serialItem;
		serialItem.append(*it);
		serialItem.append(name);
		serialItem.append(*itMime);
		serialItem.append(*itModTime);
		serialItem.append(*itMode_T);
		serialItem.append(*itSize);
		serialItem.append(*itPixmap);
		
			
	
		map.insert(*it, serialItem, TRUE);//overwrite same entries
		
		
		
		//do not return results here but use kdirlister
// 		entries += m_impl.pathToUDSEntry(  myU.pathOrURL() , name, *itMime, *itModTime, *itMode_T, *itSize, *itPixmap);
		
		
		
		//TODO: file preview thumbnails: use the .thumbnails cache : copy my stored 
		//pixmaps_thumbs to the cache: this would do all the magic, I guess
		
		//TODO: FIXME: HELP serialization of kfilemetainfo possible but of kfileitem as it is makes few sense, because kde only serializes the name the url and the text of an item
		//problem is: how to get control on those kfileitems ? 
		//only solution I would see is to create my own kpart, isn't it ?
		//but kpart are not accepted in the kfileDialog, isn't it ?? :-(((
		//use KDirNotify KDirLister ??? how to give then a full KFileItem ????
		
		itDisplay++;
		itMime++;
		itModTime++;
		itMode_T++;
		itSize++;
		itPixmap++;
// 		itItem++;

		//to much flicker here	
		//FIXME: this means we might have duplicates between chunks of 1000
		//but who cares with such a high number of items.
/*		if (chunk_counter > 1000)
		{
			chunk_counter = 0;
			listEntries(entries);
			entries.clear();		
		}*/
	}
	
	//if URI duplicates, then numbering of results will show jumps
	QMap<QString, QStringList>::Iterator itMap;
	for ( itMap = map.begin(); itMap != map.end(); ++itMap )
	{
		
		QStringList::Iterator it = itMap.data().begin();
		QString a1 = *it;
		it++;
		QString a2 = *(it);
		it++;
		QString a3 = *(it);
		it++;
		QString a4 = *(it);
		it++;
		QString a5 = *(it);
		it++;
		QString a6 = *(it);
		it++;
		QString a7 = *(it);
		
		entries += m_impl.pathToUDSEntry( a1  , a2, a3, a4, a5, a6, a7);
	}
	
	//this only list the HOME entry. Other results are coming from dirlister
	listEntries(entries);
	finished();
	kdDebug() << "KwestProtocol::processKwestHits()  STOP DIRLISTER" << m_currentURL << endl;
}

void KwestProtocol::gotDirListerCanceled(const KURL & url)
{
	kdDebug() << "KwestProtocol::gotDirListerCanceled" << url << endl;

}
void KwestProtocol::gotDirListerCanceled()
{
	kdDebug() << "KwestProtocol::gotDirListerCanceled" << endl;

}

			
void KwestProtocol::processAllHitsAreHere()
{
	kdDebug() << "KwestProtocol::processAllHitsAreHere() " << endl;

	//FIXME: because I don't send a highlighting file so far NO
	m_AllHitsAreHere = TRUE;
	m_HighlightingsReceived = TRUE;
	
	if (m_HighlightingsReceived)
	{
		emit kwestFinished();
	}
	
}

void KwestProtocol::processKwestHighlightings()
{
	m_HighlightingsReceived = TRUE;

	if (m_AllHitsAreHere)
		emit kwestFinished();
}

void KwestProtocol::processCluceneFinished()
{
	//reset some variables
	m_HighlightingsReceived =FALSE;
	m_AllHitsAreHere = FALSE;
	m_impl.setQuery    (QString::null);
// 	m_impl.m_queryName =   QString::null;
	//m_impl.setQuery_url(QString::null);
			
	infoMessage(i18n("Finished."));
	finished();
}

bool KwestProtocol::processGUIOutput()
{
	kdDebug() << "KwestProtocol::processGUIOutput() m_buff" 
			<<  m_impl.m_buf << endl;


	//must be callded from listdir
	
	// 	m_impl.m_kprocess == QString::null;
	//query is not empty: startGuiSearch has put a new query_url 
	
	if ( m_impl.m_buf.isEmpty() )
	{
		
		redirection(IOSLAVE_PROTOCOL_NAME_FULL);
		finished();
// 		error(KIO::ERR_CANNOT_OPEN_FOR_READING, "");
// 		error(KIO::ERR_NO_CONTENT, "No content or the gui didn't worked");
		return FALSE;
	}
	else
	{
		//extract query and name
		QStringList parsedBuf;
		parsedBuf = QStringList::split("/ clQN:" , m_impl.m_buf,FALSE);
		int test = parsedBuf.count();
		kdDebug() << "KwestProtocol::processGUIOutput() count"<< test <<endl; 

		if (test==1)
		{
			QString q = *(parsedBuf.at(0));
			m_impl.setQuery(q);
			//TODO:query name
		}
		
		else if (test==2)
		{
			
			QString q = *(parsedBuf.at(0));
			QString n = *(parsedBuf.at(1));
			kdDebug() << "KwestProtocol::processGUIOutput() n: "<< n 
					<< "q: "<< q <<endl; 

			m_impl.setQuery(q);
			m_impl.m_queryName = n;
		}
		else
		{
			//no query found and no name found
			m_impl.setQuery("");
			m_impl.m_queryName="";
		}
		
// 		m_impl.setQuery(m_impl.m_buf);
		QString MyQueryUrl3 = IOSLAVE_PROTOCOL_NAME_FULL + m_impl.query() ; //NO 
		QString MyQueryUrl2 = IOSLAVE_PROTOCOL_NAME_FULL + m_impl.query() + "/"; //NO 
		KURL myK = KURL(MyQueryUrl3);
		
		redirection(myK);
		finished();
		return TRUE;
	}
	return FALSE;
	
}

bool KwestProtocol::processConfigOutput()
{
	//force config reload
	//BROKEN TODO FIXME: so far, one config for any ioslave. not good
	//BROKEN BECAUSE kprocess finishes before the app is quit
	//it makes no sense to read the config here
	//what I do is check if the config file mid. time has been modified
	//and reload conf before sendng the query
	m_impl.readConfig();
	kdDebug() << "KwestProtocol::processConfigOutput() m_buff" 
			<<  m_impl.m_buf << endl;
	redirection(IOSLAVE_PROTOCOL_NAME_FULL);
	finished();
	return TRUE;
	
}

#include "kio_kwest.moc"
