/***************************************************************************
                          dchubsearch.h  -  description
                             -------------------
    begin                : Fri Mar 15 2002
    copyright            : (C) 2002-2004 by Mathias Küster
    email                : mathen@users.berlios.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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef DCHUBSEARCH_H
#define DCHUBSEARCH_H

/**
  *@author Mathias Küster
  */

#include <QTimer>
#include <QList>
#include <QHash>
#include <QMutex>
#include <QString>
#include <QCloseEvent>
#include <QFile>
#include <QWidget>

#include "DCDialogHubSearch.h"
#include "dcgui.h"
#include "dcconnectionmanager.h"

class CMessageSearchResult;
class CDCMessage;
class CMessageLog;

/* could also switch to QList */
#include <dclib/core/types.h>
#include <dclib/core/clist.h>

/* _CCallback1 is a template class so forward decls don't really work */
#include <dclib/core/ccallback.h>

class DC_ListResult;

class QMdiSubWindow;
class QEvent;
class QResizeEvent;
class QShowEvent;

enum eGroupSearchResultType {
	egsrtNONE,
	egsrtFILE,
	egsrtSIZE,
	egsrtNICK,
	egsrtSLOTS_FREE,
	egsrtSLOTS_TOTAL,
	egsrtHUB,
	egsrtPATH,
	egsrtHOST,
	egsrtHASH,
	egsrtIP
};

/**
 * Need to keep track of CSearchManager state which
 * may be changed by auto search or another search window.
 *
 * READY = no search is running (which window last used CSearchManager does not matter)
 * SEARCH = our search is running
 * OTHER = another search window is searching
 * AUTO = the auto search is running ("external" search)
 */
enum eGlobalSearchState {
	egssREADY,
	egssSEARCH,
	egssOTHER,
	egssAUTO
};

class DCWaitMagnet : public QWidget
{
  Q_OBJECT

    /**
        @author Dmitry Krivomasov
    */

public:
        DCWaitMagnet(QWidget * parent = 0);
        virtual ~DCWaitMagnet();
        void showMagnet(QString tth);
protected:
        void timerEvent(QTimerEvent *event);

private:
        int timerId;
        void testFile();
        QFile *file;
        QString magnet;
        QString key;
};

extern DCWaitMagnet * g_pWaitMagnet;

class DC_QSearchTreeWidgetItem : public QTreeWidgetItem {
public:
	/** constructor */
	DC_QSearchTreeWidgetItem( QTreeWidget * parent ) : QTreeWidgetItem( parent ) {
		p_msg = 0;
	};
	/** constructor */
	DC_QSearchTreeWidgetItem( QTreeWidgetItem * parent ) : QTreeWidgetItem( parent ) {
		p_msg = 0;
	};
	/** destructor */
	virtual ~DC_QSearchTreeWidgetItem() {};

	/** */
	CDCMessage * p_msg;
};

class DCHubSearch : public QWidget, private Ui::DCDialogHubSearch  {
Q_OBJECT

public:
	/** construtor */
	DCHubSearch( QWidget * parent = 0 );
	/** destructor */
	virtual ~DCHubSearch();

	/** Get the MDI sub window we are in */
	QMdiSubWindow * GetMdiSubWindow() { return m_pContainerWindow; } ;

	/** */
	void InitDocument();
	/** */
	void DeInitDocument();

	/** search result */
	bool DC_SearchResult( CMessageSearchResult * MessageSearchResult );

	/** callback function */
	int DC_CallBack( CDCMessage * );

	/** For searching from chat / transfer view */
	void SetSearchForFile( QString file, eFileTypes filetype = eftALL, int sizepos = 0, ulonglong size = 0 );
	/** To start search from another window prompting if another search is running */
	void StartSearchWithPrompt();

protected:
	/** Adjust column sizes preserving user set size ratios */
	void SizeColumnsPreservingRatios();
	/** resize event handler */
	virtual void resizeEvent( QResizeEvent * );
	/** overridden so that the column widths are initialized on first show() */
	virtual void showEvent( QShowEvent * event );
	/** event filter */
	virtual bool eventFilter( QObject * object, QEvent * event );
        /** */
        virtual void closeEvent( QCloseEvent *e);

private:
	/** */
	void DC_LogMessage( CMessageLog * MessageLog );
	/** */
	void AddLogMessage( QString message );
	/** */
	QString GetSearchQueryString();

	/** show all search results */
	void ShowResults( bool bClearList );

	/** */
	void SetSearchView( bool enabled );

	/** get the search string with protocol */
	CDCMessage * GetSearchObject();
	/** */
	void UpdateHidden( bool SearchFileOnly, int FreeSlots, bool Filter = false );

	/** */
	Q3ListViewItem * ShowSearchResult( CMessageSearchResult * MessageSearchResult, Q3ListView * parent );
	/** */
	Q3ListViewItem * ShowSearchResult( CMessageSearchResult * MessageSearchResult, DC_ListResult * parent );
	/** */
	bool AddSearchResult( CMessageSearchResult * MessageSearchResult, DC_ListResult * item );

	/** */
	void GroupSearchResults( eGroupSearchResultType type );
	/**
	 * Clearing the search results list also requires
	 * clearing the hash used for grouping and zeroing the empty group pointer.
	 */
	void ClearSearchResults();

	/** */
	void RemoveSelectedSearch( QList<QTreeWidgetItem*> * );

	/** */
	void startSearch();
	/** */
	void addHistory( CDCMessage * msg = 0 );
	/** Needed both for right-click and double-click */
	void DownloadFolder( Q3ListViewItem * item );

	/** store all messages from udp socket */
	CList<CDCMessage> * m_pMessageList;
	/** */
	CList<CDCMessage> * m_pSearchQueryList;
	/** store all search results */
	CList<CMessageSearchResult> * m_pSearchResultList;
	/** search history */
	CList<CDCMessage> * m_pSearchHistory;
	/** */
	QMutex SocketCallbackMutex;
	/** */
	QTimer m_Timer;
	/** current CSearchManager state */
	eGlobalSearchState m_eSearchState;
	/** */
	QMdiSubWindow * m_pContainerWindow;
	/** The last width that we adjusted the size of the file search result columns for */
	int lastFileResultsWidth;
	/** The last width that we adjusted the size of the user search result columns for */
	int lastUserResultsWidth;
	/**
	 * Our callback function which we give to CSearchManager.
	 * CSearchManager does not delete callback functions any more because
	 * multiple search windows would not work with that.
	 */
	_CCallback1<CDCMessage*> * m_pOurCallback;
	/** Current grouping */
	eGroupSearchResultType m_eCurrentGrouping;
	/** */
	QHash<QString, DC_ListResult*> m_GroupHash;
	/** */
	DC_ListResult * m_pEmptyGroup;
	/** Keep count of number of results not shown */
	int m_nFilteredResults;

private slots:
	/** */
	void timerDone();
	/** */
	void slotSearchReturnPressed();
	/** */
	void slotAddSearchQueue();
	/** */
	void slotReset();
	/** */
	void slotChangedFreeSlots( int free_slots );
	/** */
	void slotToggledSearchFileOnly( bool chkstate );
	/** */
	void slotDoubleClickedSearchResult( Q3ListViewItem * item );
	/** */
	void slotRightButtonClickedSearchResult( Q3ListViewItem *, const QPoint &, int );
	/** current tab widget change slot */
	void slotTabWidgetCurrentChange(QWidget*);
	/** */
	void slotRefreshConnectedHubs();
	/** */
	void slotTextFilterResults();
	/** */
	void slotTextFilterReset();
	/** */
	void slotContextMenuSearch( const QPoint & );
	/** */
	void slotSearchSelected(int);
	/** */
	void slotPurgeHistory();
	/** */
	void slotSizeLimitChanged(int index);
signals:
        void onDie(QWidget*);
public slots:
	void slotUpdateGrouping(int index);
};

#endif
