/***************************************************************************
 *   Copyright (C) 2005 by xavier helluy   *
 *   xavier.helluy@web.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 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         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/

#ifndef KCLUCENEINDEXERDAEMON_H
#define KCLUCENEINDEXERDAEMON_H

#include <qobject.h>
#include <qobject.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qmap.h>

#include <dcopclient.h>
#include <dcopobject.h>

#include <kio/netaccess.h>
#include <kio/job.h>

#include <kurl.h>
#include <kfileitem.h>
#include <kfile.h>
#include <kdebug.h>
#include <kprocess.h>

#include <dcopclient.h>
#include "kclucene_indexer_daemon_dcopiface.h"
    
#include <CLucene.h>
// #include "CLucene/util/Reader.h"
//Includes some standard headers for searching and indexing.
#include <CLucene/index/IndexReader.h>
#include <CLucene/index/IndexWriter.h>
#include <CLucene/index/Term.h>
#include <CLucene/search/IndexSearcher.h>
#include <CLucene/document/Document.h>
#include <CLucene/document/Field.h>
#include <CLucene/document/DateField.h>
#include <CLucene/store/Directory.h>
#include <CLucene/store/FSDirectory.h>
#include <CLucene/queryParser/QueryParser.h>
#include <CLucene/analysis/standard/StandardAnalyzer.h>
#include <CLucene/analysis/Analyzers.h>

#include <CLucene/search/SearchHeader.h>
#include <CLucene/search/TermQuery.h>

#include <iostream>

#include "converters.h"
#include <kfileitem.h>
#include <qmap.h>


/**
@author xavier helluy
 */

	using namespace std;
	// namespace lucene{ namespace demo {
	using namespace lucene::index;
	using namespace lucene::analysis;
	using namespace lucene::util;
	using namespace lucene::store;
	using namespace lucene::document;

// 	typedef QPtrList<KFileItem> KFileItemList
	
	class KCLuceneIndexerDaemon : public QObject , virtual public KCLuceneIndexerDaemonDCOPIface
{
	Q_OBJECT

	public:
		KCLuceneIndexerDaemon();
		~KCLuceneIndexerDaemon();
		
	public slots:	
		void timerDone();
		void startIndexing();
		void startNewIndexRequest();
		void startDeleteHits();
		void slotEntries( KIO::Job*, const KIO::UDSEntryList& lst );
		void slotMetaInfoGot(const KFileItem *);
		void slotMetaInfoFailed(const KFileItem *);
		
		void slotPreviewGot(const KFileItem *, const QPixmap & );
		
		void slotSyncTextConversionFinished(KProcess * );
		
		int deleteHits(
				const QString & 		callingClientId,
				const QString &  		indexName,
				const QString &      		indexLocation,
				const QString &			query
			      );
		
		int doIndex(
				const QString & 		callingClientId,
				const QString &  		indexName,
				const QString &      		indexLocation,
				const bool & 			boolMetaData,		//ok
				const bool &			boolContent,		//ok
				const bool &			boolArchives,		//ok
				const bool &			includeSubFolders,	//ok
				const bool &			excludeSubFolders,	//TODO
				const QStringList & 		includeItems,		//ok
				const QStringList & 		excludeItems,		//TODO
				const bool &			addToIndex,		//ok with
				const bool &			eraseIndex,		//ok 
				const bool &			eraseMedia,		//ok 
				const bool &			updateIndex,		//TODO
				const bool &			syncIndex,		//TODO
				const QStringList &		tmpMimeList,
				const QStringList &		tmpMimeProc, 
				const QStringList &		tmpMimeArgs,
				const QStringList &		tmpMimeOutput,
				const QStringList &		tmpPatternList,
				const QStringList &		tmpPatternProc,
				const QStringList &		tmpPatternArgs,
				const QStringList &		tmpPatternOutput,
				const bool & 			tmpText,
				const bool & 			tmpHtml,
				const bool & 			tmpXml,
				const bool &		tmpRestrictMetaData,
				const QString &      		mediaType,
				const QString &      		mediaName
			   );

		
	signals:
		void indexRequestReceived();
		void deleteHitsCallReceived();
	private:	
		//four indexing modes
		void startOverWriteMode();
		void startOverWriteMediaMode();

		void startAppendMode();
		void startUpdateMode();
		void startSyncMode();
		
		void eraseMediaEntries();

		void initIndexDirectory(const QString & indexName, const bool & overWriteMode);
		void initIndexWriter(Directory * d, lucene::analysis::standard::StandardAnalyzer * an,
				     bool overWrite);
		
		void flushAndCloseIndex(IndexWriter * writer);
		
		void indexingLoopOverItems( KFileItemList & itemsList, bool updateMode, bool cleanUp, QString visualPathName = "");
		void indexingLoopOverIndexEntries();
		QString URLToURLKey(const QString &URLstr);
		QString URLToURLKey(const KURL & URL);
		QString URLKeyToURL(const QString &URLstr);
		QString getConfigNumber(KFileItem * item);
		bool hasConfigChanged(Document & doc,KFileItem * item);




		
		//write item to index if accepted
		void indexItems( KFileItemList & items);
		bool indexEntry( KFileItem * item);
		void indexDigikamQMap();
		
		//returns TRUE if the item in the Index must be indexed again. 
		//Delete old entry in Index if existing and old Mod. Time
		bool updateEntry( KFileItem * item);

		//returns TRUE if the item in the Index must be indexed again.
		//Delete old entry in Index if existing and old Mod. Time
		bool syncEntry(Document & doc, int docNumber, const QString &urlString, KFileItem * item);
		
		//check if it is allowed to index  this item
		bool isURLExcluded(const KFileItem * item);
		
		//check if it is allowed to loop ito this item, if it is a dir
		bool isIndexingDirContentAllowed(KFileItem * item, bool);
		
		void closeReaderAndSearcher();
		void openReaderAndSearcher();

		bool listDir(KURL u);

		void buildDigikamQMap(const QString & digikamURL,   KFileItemList & lst);
		void writeDigikamQMap();

		void listDirEntriesToKFileItemList(const KIO::UDSEntryList & lst, KFileItemList & itemList, const KURL  u,  KURL * realURL);
		void stringListToKFileItemList( QStringList & includeURLs, KFileItemList & itemList, bool fromDir);
		
		bool hasModTimeChanged( Document & doc,  KFileItem * item);
// 		lucene::search::Hits * fromURLToIndexHits(QString urlString);
		
		bool isFileTypeWanted(KFileItem * item);
		bool isMetaDataWanted(KFileItem * item);
		bool hasFileTypeAConverter(KFileItem * item);
		bool hasExternalConverter(KFileItem * item);
		bool isContentWanted(KFileItem * item);

		//cleanup metadata fields before indexing
		QString stripMetaData(QString str);
		void builtinReader(KFileItem * item);
		bool getContentToTmpFile(KFileItem * item, KTempFile * tmpFile);
		void startSyncDocToTextConversion();
		
		int doAllMetaDataIndexing(KFileItem * item, QString & anystring);

		bool doStorePreview( KFileItem * selectedItem, KURL & realURL);
		
		void doTimesIndexing(KFileItem * item);
		int doURLandMediaAndMimetypeIndexing(KFileItem * item , QString & anyStringExeptContent);
		bool metaInfoJob(KFileItem * item);
		void doContentIndexing(KFileItem * item);

		
		bool m_metaInfo;



		QPixmap m_pixmap;

		bool checkIfIndexExists(QString indexName);
		KIO::UDSEntry  		m_entry; 		//used by statjob
		KIO::UDSEntryList 	m_tmpUDSEntryList;	//used by listdirJob
		
		//quit
		QTimer * m_timer;
		
		// clucene index
		QString 		m_indexName;
		QString			m_indexLocation;

		bool 			m_includeSubFolders;
		bool	 		m_excludeSubFolders;
		bool 			m_insideArchive;
		QStringList  		m_includeItems;		//ok
		QStringList  		m_excludeItems;
		
		lucene::search::IndexSearcher *			m_idSearcher;
		lucene::index::IndexReader *   			m_idReader;
		IndexWriter * 					m_writer;
		lucene::analysis::standard::StandardAnalyzer * 	m_an;
		lucene::store::Directory * 			m_d;
		Document *					m_doc;
		
		//client requested MODES and related variables
		bool m_overWriteIndex; 
		bool m_overWriteMedia;
		bool m_syncIndex;
		bool m_appendIndex;
		bool m_updateIndex;
		KFileItemList m_itemsToIndex;
		int m_countEntriesToIndex;
		int m_counterRunOptimize;
		int m_maxEntriesToIndex;
		int m_maxIndexedEntries;
		int m_countIndexedEntries;
		
		//there can be many tags for a url and many urls for a tags
		//lucene can add n-time the same field.But can it search on all same fields 
		QStringList m_digikamListURLs;
		QStringList m_digikamListTags;
		// variables used to really do the indexing job
		//converters
		Converters *		m_convert;	//to converters ok
		//needed variables
		QString       		mediaType;
		QString       		mediaName;
		bool 			m_allMetaData;		//ok
		bool 			m_content;		//ok
		bool			m_readerText;  		//ok
		bool			m_readerHtml;  		//ok
		bool			m_readerXml;   		//ok
		bool			m_restrictMetaData;	//ok
		QString			m_mediaName;
		QString			m_mediaType;
		QString			m_mode;
		
		//dcop caller
		QString  m_callingClient;
		
		//used to deletes some entry on request. Not implemented functionality
		QString  m_query;
};

#endif

