/***************************************************************************
                          csearchmanager.h  -  description
                             -------------------
    begin                : Thu May 27 2004
    copyright            : (C) 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 CSEARCHMANAGER_H
#define CSEARCHMANAGER_H

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

#include <time.h>

#include <dclib/dcos.h>
#include <dclib/core/cstring.h>
#include <dclib/core/cconnection.h>
#include <dclib/core/csingleton.h>
#include <dclib/cclient.h>
#include <dclib/csearchsocket.h>

class CSearchManager;

#ifdef WIN32
template class DLL_EXPORT CSingleton<CSearchManager>;
#endif

/** */
class DLL_EXPORT CSearchClient : public CClient {
public:
	/** */
	CSearchClient() {
		m_bSearchRemove = FALSE;
		m_bSearchEnable = FALSE;
		m_pCurrentSearchObject = 0;
		m_tSearchTimeout = 0;
	};
	/** */
	virtual ~CSearchClient() {};

	/** */
	bool m_bSearchRemove;
	/** */
	bool m_bSearchEnable;
	/** */
	time_t m_tSearchTimeout;
	/** */
	CObject * m_pCurrentSearchObject;
};

/** search modes */
typedef enum eSearchMode {
	esmCONNECTEDSINGLE = 0,
	esmCONNECTEDALL,
	esmPUBLIC,
	esmBOOKMARK
} eSearchMode;

typedef enum eSearchState {
	esNONE = 0,
	esSEARCH,
	esTIMEOUT,
	esSTOP
} eSearchState;

/** */
typedef enum eSearchError {
	eseNONE = 0,
	eseALREADYRUN
} eSearchError;

/** */
typedef enum eSearchType {
	estyNONE = 0,
	estySINGLE,
	estyMULTI,
	estyEXTERNAL
} eSearchType;

class _CCallback;

/** */
class DLL_EXPORT CSearchManager : public CSingleton<CSearchManager> {
public:
	/** */
	CSearchManager();
	/** */
	virtual ~CSearchManager();

	/** */
	int CallBackManager( CObject *, CObject * );
	/** */
	int CallBackClient( CObject * Client, CObject * Object );
	/** */
	int CallBackSearchSocket( CObject *, CObject * );

	/** */
	eSearchError StartSearch( eSearchMode mode, eSearchType type, CList<CObject> * querylist, CStringList * serverlist );
	/** */
	void StopSearch();

	/** */
	bool HandleSearch( CObject * object );

	/** */
	enum eSearchType SearchType() { return m_eSearchType; }
	/** */
	long MaxClients() { return m_nMaxClients; }
	/** */
	void MaxClients( long n ) { m_nMaxClients = n; }
	/** */
	void EnableTag( bool b ) { m_bEnableTag = b; }

	/** */
	bool IsSearch() { return (m_eSearchType != estyNONE); }

	/** */
	eSearchState SearchState() { eSearchState e; m_Mutex.Lock(); e = m_eSearchState; m_Mutex.UnLock(); return e; }
	/** */
	void SearchState( eSearchState e ) { m_Mutex.Lock(); m_eSearchState = e; m_Mutex.UnLock(); }

	/** */
	void SetCallBackFunction( _CCallback * callback );
	
	/** */
	time_t StartTime() { return m_tStartTime; };
	/** */
	long HubCount();
	/** */
	long HubIndex() { return m_nHubIndex; };
	/** */
	long HubError() { return m_nHubError; };
	
protected:

private:
	/** */
	bool AddClients();
	/** */
	bool AddClient();
	/** */
	void UpdateClients();
	/** */
	bool RemoveClients();
	/** */
	void DisconnectClients();
	/** */
	bool DoSearch( CSearchClient * HubSearchClient );
	/** */
	bool SendObject( CObject * object );
	
	/** manager callback */
	_CCallback * m_pCallback;
	/** */
	CMutex m_Mutex;
	/** client list */
	CList<CSearchClient> * m_pClientList;

	/** max simultan clients */
	long m_nMaxClients;
	/** current hub index */
	long m_nHubIndex;
	/** hub with errors */
	long m_nHubError;
	/** current hub */
	CString * m_sCurrentHub;
	
	/** hub list */
	CStringList * m_pHubList;
	/** */
	CList<CObject> * m_pSearchList;
	/** only for passive searches */
	CObject * m_pCurrentSearchObject;

	/** */
	bool m_bEnableTag;
	/** */
	bool m_bHandleUserList;

	/** */
	CSearchSocket m_SearchSocket;

	/** starttime */
	time_t m_tStartTime;
	/** timeout */
	time_t m_tTimeoutTime;

	/** search type */
	enum eSearchType m_eSearchType;
	/** search state */
	enum eSearchState m_eSearchState;
	/** search mode */
	enum eSearchMode m_eSearchMode;
	/** client mode */
	enum eClientMode m_eClientMode;

	/** callback function */
	_CCallback * m_pParentCallback;
};

/** */
inline void CSearchManager::SetCallBackFunction( _CCallback * callback )
{ m_Mutex.Lock(); if ( m_pParentCallback ) delete m_pParentCallback; m_pParentCallback = callback; m_Mutex.UnLock(); }

#endif
