//
// C++ Implementation: findManager
//
// Description: 
//
//
// Author: Nicolas Ternisien <nicolas.ternisien@gmail.com>, (C) 2005
//
// Copyright: See COPYING file that comes with this distribution
//
//

//Project includes
#include "findManager.h"

#include "ksystemlog.h"


FindManager::FindManager(KSystemLog* parent, const char* name) :
	TQObject(parent, name),
	main(parent),
	findDialog(NULL),
	findManager(NULL),
	previousItemFound(NULL),
	currentItemFound(NULL) {
	
	
}

FindManager::~FindManager() {
	if (findDialog!=NULL)
		delete findDialog;
		
	if (findManager!=NULL)
		delete findManager;
}

void FindManager::slotFind() {

	if (findManager!=NULL) {
		delete findManager;
		findManager=NULL;
	}
	
	if (findDialog==NULL) {
		kdDebug() << "KFindDialog creation" << endl;
		//TODO Save the Find options to Config file
		findDialog=new KFindDialog(false, main, "find_dialog");
		connect(findDialog, TQ_SIGNAL(okClicked()), this, TQ_SLOT(slotFindNext()));
	
		findDialog->show();
	}
	else {
		findDialog->show();
	
		//KWin::activateWindow(findDialog->winId());
		//return;
	}

}


void FindManager::slotFirstFind() {
	kdDebug() << "First Find" << endl;
	
	LogManager* currentManager=main->activeLogManager();
	TDEListView* list=currentManager->getView()->getLogList();
	
	//Delete the previous KFind object (if it exists)
	if (findManager!=NULL) {
		delete findManager;
		findManager=NULL;
	}

	//TODO Is useful?
	if (previousItemFound!=NULL) {
		list->setSelected(previousItemFound, false);
	}
	
	//This creates a find-next-prompt dialog if needed.
	findManager=new KFind(findDialog->pattern(), findDialog->options(), main, findDialog);
	connect(findManager, TQ_SIGNAL(highlight(const TQString&, int, int)), this, TQ_SLOT(highlightSearch(const TQString&, int, int)));
	connect(findManager, TQ_SIGNAL(findNext()), this, TQ_SLOT(slotFindNext()));
	
	//Do not keep the KFindDialog open
	findDialog->hide();
	
	
	//findManager->closeFindNextDialog();
	
	TQListViewItemIterator it(list, TQListViewItemIterator::Selected);
	int itemPos=-1;
	int currentPos;
	while (it.current()) {
		list->setSelected(it.current(), false);
		
		currentPos=list->itemPos(it.current());
		if (currentPos>=itemPos) {
			itemPos=currentPos;
			previousItemFound=static_cast<LogListItem*> (it.current());
		}
		
		++it;
	}
	//Unselect all previous items (the last one if always selected)
	if (previousItemFound!=NULL)
		list->setSelected(previousItemFound, true);
	
	
	
	//If we search from the cursor, the iterator goes to the first selected item
	if (findDialog->options() & KFindDialog::FromCursor) {
		currentItemFound=currentManager->getView()->getFirstSelectedItem();
		
		//If nothing is selected, then we initialize the iterator classicaly
		if (currentItemFound==NULL) {
			currentItemFound=static_cast<LogListItem*> (list->firstChild());
		}
		
		previousItemFound=currentItemFound;
	}
	//If we search from the last, the iterator is initialized to the last item
	else if (findDialog->options() & KFindDialog::FindBackwards) {
		currentItemFound=static_cast<LogListItem*> (list->lastItem());
	}
	//Default initialization
	else {
		currentItemFound=static_cast<LogListItem*> (list->firstChild());
	}
	
}

void FindManager::slotFindNext() {
	//If we attempt to go to the next search, without have opened the find dialog, we open it
	if (findDialog==NULL) {
		slotFind();
		return;
	}
	
	//If the KFind object has not been initialized, we call the right method for that
	if (findManager==NULL) {
		slotFirstFind();
	}

	
	//Keep the Find Dialog opened
	/*
	if (findManager->options() != findDialog->options() || findManager->pattern()!=findDialog->pattern()) {
		kdDebug() << "Reinitialize the search..." << endl;
		slotFirstFind();
	}
	*/


	KFind::Result res = KFind::NoMatch;
	while (res==KFind::NoMatch && currentItemFound!=NULL) {

		//Always need new data, because a line is only selected one time
		//if (findManager->needData())
			findManager->setData(currentItemFound->exportToText());

		//Let KFind inspect the text fragment, and display a dialog if a match is found
		res=findManager->find();

		//Always need new data, because a line is only selected one time
		//if (res==KFind::NoMatch ) {
			if (findDialog->options() & KFindDialog::FindBackwards)
				currentItemFound=static_cast<LogListItem*> (currentItemFound->itemAbove());
			else
				currentItemFound=static_cast<LogListItem*> (currentItemFound->itemBelow());
		//}
	}


	//End of the view
	if (res==KFind::NoMatch) {
		if (findManager->shouldRestart()) {
			delete findManager;
			findManager=NULL;
			findDialog->setOptions(findDialog->options() & !KFindDialog::FromCursor);
			slotFindNext();
		}
		else {
			findManager->closeFindNextDialog();
		}
	}

}


void FindManager::highlightSearch(const TQString& /*text*/, int /*matchingIndex*/, int /*matchingLength*/) {
	LogManager* currentManager=main->activeLogManager();
	TDEListView* list=currentManager->getView()->getLogList();
		
	if (previousItemFound!=NULL) {
		list->setSelected(previousItemFound, false);
	}
	
	if (currentItemFound!=NULL) {
		list->setSelected(currentItemFound, true);
		list->ensureItemVisible(currentItemFound);
		previousItemFound=currentItemFound;
	}

}


#include "findManager.moc"
