/***************************************************************************
                          cclient.h  -  description
                             -------------------
    begin                : Sun Sep 30 2001
    copyright            : (C) 2001-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 CCLIENT_H
#define CCLIENT_H

/**
  *@author Mathias Küster
  *
  * A hub connection.
  */

#include <dclib/dcos.h>
#include <dclib/core/cstring.h>
#include <dclib/core/ccallback.h>
#include <dclib/dcobject.h>
#include <dclib/cdcproto.h>
#include <dclib/cclientssl.h>
#include <dclib/cuserlist.h>

/** */
enum eReconnectState {
	ersNONE,
	ersFORCEMOVE,
	ersDISABLED,
	ersENABLED
};

/* added for zpipe data buffer */
class CZLib;

class CMessageHandler;

class CClient : public CDCProto {

public:
	/** */
	CClient( CString remoteEncoding = CString() );
	/** */
	virtual ~CClient();

	/** */
	bool SetUserTransferInfo( CString nick, CDCMessage * msg );

	/** */
	inline void SetHubName( CString hubname );
	/** */
	inline CString GetHubName() const;
	/** */
	inline void SetHubTopic( CString hubtopic );
	/** */
	inline CString GetHubTopic() const;
	
	/** */
	inline void SetNick( CString nick );
	/** */
	inline CString GetNick() const;
	/** */
	inline void SetEMail( CString email );
	/** */
	inline CString GetEMail() const;
	/** */
	inline void SetConnectionType( CString ctype );
	/** */
	inline CString GetConnectionType() const;
	/** */
	inline void SetComment( CString comment );
	/** */
	inline CString GetComment() const;
	/** */
	inline void SetShareSize( ulonglong sharesize );
	/** */
	inline ulonglong GetShareSize() const;
	/** */
	inline void SetMode( eClientMode mode );
	/** */
	inline eClientMode GetMode() const;
	/** */
	inline void SetAwayMode( eUserAwayMode mode );
	/** */
	inline eUserAwayMode GetAwayMode() const;
	/** True if a password was used to log in to the hub */
	inline bool GetUsedPassword() const;
	/** */
	inline void SetUsedPassword( bool b );
	/** */
	inline void SetMyInfoTLSFlag( bool b );
	
	/** Returns true if supports UserIP2 */
	inline bool GetSupportsUserIP2() const;
	/** Returns true if supports NoGetINFO */
	inline bool GetSupportsNoGetInfo() const;
	
	/** */
	bool IsTLSInMyInfo() const { return m_MyInfo.m_bTLSFlag; };
	
	/** */
	inline bool IsHandshake() const;
	/**
	 * Returns our external IP address, either the last one given to us
	 * by the hub or gets the one from CConfig depending on settings.
	 * The port added is a TCP port (standard or TLS).
	 */
	CString GetExternalIP( bool addport = true, bool cryptoport = false ) const;
	
	/** */
	inline void SetHandleUserList( bool b );
	/** */
	inline void SetHandleSearch( bool b );
	/** */
	inline void SetHandleMyinfo( bool b );
	/** */
	inline void SetSendMyinfo( bool b );
	/** */
	inline void SetHandleForceMove( bool b );
	/** */
	inline void SetHandleTransfer( bool b );
	/** */
	inline void SetSSLMode( bool b );

	/** */
	inline CUserList * UserList() { return &m_UserList; };

	/** */
	inline void SetCallBackFunction( _CCallback2<CClient, CDCMessage*> * callback );

	/** */
	int HandleMessage( const CString & message );

	/** send private message */
	virtual int SendPrivateMessage( CString sNick, CString sTo, CString sMsg, CString sFromNick = CString() );
	/** */
	virtual int RequestNickList();

	/** */
	virtual void DataAvailable( const char * buffer, int len );
	/** */
	virtual void DataTimeout();
	/** */
	virtual void Notify();
	/** */
	virtual void ConnectionState( eConnectionState state );
	/** callback function */
	virtual int DC_CallBack( CDCMessage * ) { return -1; };

	/** */
	int Disconnect( bool force = false );
	
	/** Overridden to use our external IP for active and our nick for passive searches */
	int SendSearch( CMessageSearchFile * msg );

protected:
	/** */
	void UpdateReconnect( eReconnectState state, int count = -1 );

private:
	/** Send SSL log messages to GUI */
	void SendSSLInfo();

	/** user list */
	CUserList m_UserList;
	/** */
	CClientSSL m_pMessageSSL;
	/** user myinfo */
	CMessageMyInfo m_MyInfo;
	/** hubname */
	CString m_sHubName;
	/** hubtopic */
	CString m_sHubTopic;
	/** Our External IP address */
	CString m_sExternalIP;

	/** */
	bool m_bHandshake;
	/** */
	bool m_bSSLMode;
	/** */
	bool m_bHandleUserList;
	/** */
	bool m_bHandleSearch;
	/** */
	bool m_bHandleMyinfo;
	/** */
	bool m_bHandleForceMove;
	/** */
	bool m_bHandleTransfer;
	/** */
	bool m_bUpdateMyinfo;
	/** */
	bool m_bSendMyinfo;
	/** */
	bool m_bUsedPassword;
	/** */
	time_t m_timeMyinfoTimeout;
	
	/** */
	CString m_sBuffer;
	/** callback function */
	_CCallback2<CClient, CDCMessage*> * m_pCallback;
	/** */
	CMutex m_ClientMutex;
	/** */
	time_t m_timeReconnectTimeout;
	/** */
	eReconnectState m_eReconnectState;
	/** */
	int m_nReconnectCount;
	/** */
	int m_nNickListHandler;
	/**
	 * Apparently the whole client - hub supports negotiation is useless
	 * and we must assume all features we asked for have been enabled.
	 *
	 * This is always set to true on hubs with a lock that starts with
	 * EXTENDEDPROTOCOL and assumes NoGetINFO and NoHello support are enabled.
	 *
	 * Because there is no way to be sure features we did no ask for have
	 * been enabled anyway, there is no point keeping track of what we asked for
	 * and better handle everything anyway.
	 */
	bool m_bExtProtocol;
	/**
	 * This is set to true if we were assigned a valid IP
	 * address by the hub.
	 */
	bool m_bGotIP;
	/** Stream decompress zpipe data as we received it */
	CZLib * m_pZLib;
	/** True if expecting to receive zpipe data */
	bool m_bZMode;
	
	/** Keep a CMessageHandler around, it saves opening and closing iconv */
	CMessageHandler * m_pMessageHandler;
};

/** inline functions */

/** */
inline void CClient::SetNick( CString nick )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_sNick != nick ) { m_bUpdateMyinfo = true; m_MyInfo.m_sNick=nick; } m_ClientMutex.UnLock(); }
/** */
inline CString CClient::GetNick() const
{ return m_MyInfo.m_sNick; }
/** */
inline void CClient::SetEMail( CString email )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_sEMail != email ) { m_bUpdateMyinfo = true; m_MyInfo.m_sEMail=email; } m_ClientMutex.UnLock(); }
/** */
inline CString CClient::GetEMail() const
{ return m_MyInfo.m_sEMail; }
/** */
inline void CClient::SetConnectionType( CString ctype )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_sUserSpeed != ctype ) { m_bUpdateMyinfo = true; m_MyInfo.m_sUserSpeed=ctype; } m_ClientMutex.UnLock(); }
/** */
inline CString CClient::GetConnectionType() const
{ return m_MyInfo.m_sUserSpeed; }
/** */
inline void CClient::SetComment( CString comment )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_sComment != comment ) { m_bUpdateMyinfo = true; m_MyInfo.m_sComment=comment; } m_ClientMutex.UnLock(); }
/** */
inline CString CClient::GetComment() const
{ return m_MyInfo.m_sComment; }
/** */
inline void CClient::SetShareSize( ulonglong sharesize )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_nShared != sharesize ) { m_bUpdateMyinfo = true; m_MyInfo.m_nShared = sharesize; } m_ClientMutex.UnLock(); }
/** */
inline ulonglong CClient::GetShareSize() const
{ return m_MyInfo.m_nShared; }
/** */
inline void CClient::SetMode( eClientMode mode )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_eClientMode != mode ) { m_bUpdateMyinfo = true; m_MyInfo.m_eClientMode=mode; } m_ClientMutex.UnLock(); }
/** */
inline eClientMode CClient::GetMode() const
{ return m_MyInfo.m_eClientMode; }
/** */
inline void CClient::SetAwayMode( eUserAwayMode mode )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_eAwayMode != mode ) { m_bUpdateMyinfo = true; m_MyInfo.m_eAwayMode = mode; } m_ClientMutex.UnLock(); }
/** */
inline eUserAwayMode CClient::GetAwayMode() const
{ return m_MyInfo.m_eAwayMode; }
/** */
inline void CClient::SetMyInfoTLSFlag( bool b )
{ m_ClientMutex.Lock(); if ( m_MyInfo.m_bTLSFlag != b ) { m_bUpdateMyinfo = true; m_MyInfo.m_bTLSFlag = b; } m_ClientMutex.UnLock(); }

/** */
inline void CClient::SetHubName( CString hubname )
{ m_ClientMutex.Lock(); m_sHubName = hubname; m_ClientMutex.UnLock(); }
/** */
inline CString CClient::GetHubName() const
{ return m_sHubName; }
/** */
inline void CClient::SetHubTopic( CString hubtopic )
{ m_ClientMutex.Lock(); m_sHubTopic = hubtopic; m_ClientMutex.UnLock(); }
/** */
inline CString CClient::GetHubTopic() const
{ return m_sHubTopic; }
inline bool CClient::GetUsedPassword() const
{ return m_bUsedPassword; }
inline void CClient::SetUsedPassword( bool b )
{ m_ClientMutex.Lock(); m_bUsedPassword = b; m_ClientMutex.UnLock(); }


/** */
inline bool CClient::IsHandshake() const
{ return m_bHandshake; }
/** */
inline void CClient::SetCallBackFunction( _CCallback2<CClient, CDCMessage*> * callback )
{ m_ClientMutex.Lock(); delete m_pCallback; m_pCallback = callback; m_ClientMutex.UnLock(); }
/** */
inline void CClient::SetHandleUserList( bool b )
{ m_ClientMutex.Lock(); m_bHandleUserList = b; m_ClientMutex.UnLock(); }
/** */
inline void CClient::SetHandleSearch( bool b )
{ m_ClientMutex.Lock(); m_bHandleSearch = b; m_ClientMutex.UnLock(); }
/** */
inline void CClient::SetHandleMyinfo( bool b )
{ m_ClientMutex.Lock(); m_bHandleMyinfo = b; m_ClientMutex.UnLock(); }
/** */
inline void CClient::SetSendMyinfo( bool b )
{ m_ClientMutex.Lock(); m_bSendMyinfo = b; m_ClientMutex.UnLock(); }
/** */
inline void CClient::SetHandleForceMove( bool b )
{ m_ClientMutex.Lock(); m_bHandleForceMove = b; m_ClientMutex.UnLock(); }
/** */
inline void CClient::SetHandleTransfer( bool b )
{ m_ClientMutex.Lock(); m_bHandleTransfer = b; m_ClientMutex.UnLock(); }
/** */
inline void CClient::SetSSLMode( bool b )
{ m_ClientMutex.Lock(); m_bSSLMode = b; m_ClientMutex.UnLock(); }
/** */
inline bool CClient::GetSupportsUserIP2() const
{ return m_bGotIP; }
/** */
inline bool CClient::GetSupportsNoGetInfo() const
{ return m_bExtProtocol; }

#endif
