///////////////////////////////////////////////////////////////////////////////
/// @file deNetUser.hpp
///
/// @brief 
///
/// @author trajar
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Jun 2002
/// @author trajar
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////

#ifndef	_DENETUSER_HPP
#define _DENETUSER_HPP

#ifndef		_DENET_HPP
 #include	"deNet.hpp"
#endif

#ifndef		_DESYNCHOBJECT_HPP
 #include	"deSynchObject.hpp"
#endif

class deThread;
class deNetMsg;
class dePacket;
class deConnection;

typedef class DENET_API deNetUser
{
public:

	enum eNetStatus
	{
		STATUS_UNKNOWN = -1,
		STATUS_CREATED,
		STATUS_CONNECTED,
		STATUS_CLOSED,
		STATUS_DESTROYED,
	};

	enum eType
	{
		TYPE_UNKNOWN = 0,
		TYPE_MASTER_SERVER,
		TYPE_SLAVE_SERVER,
		TYPE_CLIENT,
		TYPE_PEER,
	};

	deNetUser(void);
	virtual ~deNetUser(void);

	eNetError			Init( int pType, DWORD dwFlags = NULL );
	eNetError			Destroy( DWORD dwFlags = NULL );
	eNetError			CloseConnection( DWORD dwFlags = NULL );
	virtual eNetError	SendToAll( WORD pMsgID, void * pData, DWORD pDataSize, DWORD dwFlags );
	eNetError			SendToUsers( WORD pMsgID, hNetUser * pUsers, DWORD pNumUsers, void * pData, DWORD pDataSize, DWORD dwFlags );
	eNetError			SendTo( WORD pNetMsgID, hNetUser hUser, void * pData, DWORD pDataSize, DWORD dwFlags );
	eNetError			HandleNetMsg( deNetMsg * pMsg );
	
	bool				IsNetIDUnique( hNetUser pUser );
	eNetError			ReleaseNetID( hNetUser pUser );
	hNetUser			GenerateNetID(void);

	void				AssignNetHandle( hNetUser handle);
	hNetUser			GetNetHandle(void);
	eNetStatus			GetNetStatus(void);
	eType				GetNetType(void);
	deNetAddress *		GetAddress(void);
	deSynchObject *		GetSynchObject(void);

#ifdef DN_SESSION_TIME_INT64
	void				UpdateSessionTime( s64 pTime );
	s64					GetSessionTime(void);
	s64					GetApproxSessionTime(void);
	s64					GetSessionTimeDelta(void);
#else
	void				UpdateSessionTime( float pTime );
	float				GetSessionTime(void);
	float				GetApproxSessionTime(void);
	float				GetSessionTimeDelta(void);
#endif

	virtual eNetError	OnTick( void );
	virtual deConnection *	GetConnectionByUser( hNetUser pUser );

protected:

	//-------------------------------------------------------------------------------------
	// Override these methods in your deNetUser classes
	//-------------------------------------------------------------------------------------
	virtual eNetError	OnCustomMsg( deNetMsg * pMsg )								= 0;
	virtual eNetError	OnNewConnection( deConnection * pConn )						= 0;
	virtual eNetError	OnRemoveConnnection( deConnection * pConn )					= 0;

	//-------------------------------------------------------------------------------------
	// Leave these alone, or call in a overidden method
	//-------------------------------------------------------------------------------------
	virtual eNetError	OnDestroy( DWORD dwFlags = NULL )							= 0;
	virtual eNetError	OnInit( int pType, DWORD dwFlags = NULL )					= 0;
	virtual eNetError	OnCloseConnection( DWORD dwFlags )							= 0;
	virtual eNetError	OnConnectionLost( deConnectionLost * pLost )				= 0;
	virtual eNetError	OnConnectionRequest( deConnectionRequest * pRequest )		= 0;
	virtual eNetError	OnConnectionReply( deConnectionReply * pReply )				= 0;
	
	deConnection	*	m_Connection;
	eType				m_Type;
	eNetStatus			m_Status;

#ifdef DN_SESSION_TIME_INT64
	s64					m_SessionTime;
	s64					m_SessionTimeDelta;
#else
	float				m_SessionTime;
	float				m_SessionTimeDelta;
#endif
		
private:

	deSynchObject		m_SynchObject;
	deNetAddress		m_Address;
	hNetUser			m_NetHandle;
	deThread	*		m_ServiceThread;
	
} deNetUser, *pdeNetUser;

#endif