///////////////////////////////////////////////////////////////////////////////
/// @file deConnection.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	_DECONNECTION_HPP
#define	_DECONNECTION_HPP

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

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

#ifndef		_DEPACKETLIST_HPP
 #include	"dePacketList.hpp"
#endif

#include	<SET>
typedef		std::set< dePacketList > aPacketLists;

class dePacket;
class deNetUser;
class deConnectionBin;

//---------------------------------------------------
// deConnection
//---------------------------------------------------
typedef class DENET_API deConnection
{
	friend class deConnectionProvider;

public:

	enum fFlags
	{
		FLAG_FORCE_DISCONNECT			= 0x0002,
		FLAG_CONFIRM_DELIVERY			= 0x0004,
	};

	enum eType
	{
		TYPE_UNKNOWN = 0,
		TYPE_TCP,
		TYPE_UDP,
		TYPE_DPLAY,
		TYPE_BSD
	};

	deConnection(void);
	virtual ~deConnection(void);

	eNetError			ConnectTo( deNetAddress * pAddress );
	eNetError			AttemptReset( DWORD dwFlags = NULL );
	eNetError			Disconnect( DWORD dwFlags = NULL );
	eNetError			BindAsServer( DWORD dwFlags = NULL );
	eNetError			Send( WORD pNetMsgID, const void * pBuff, DWORD iSize, DWORD  dwFlags = NULL );
	eNetError			RecievePacket( dePacket * pPacket, DWORD dwFlags = NULL );


	deConnectionBin *	GetConnectionBin( void );
	void				SetConnectionBin( deConnectionBin * pBin );
	void				SetOwner( deNetUser * own );
	DWORD				GetDesc(void);
	eType				GetType(void);
	bool				IsReady(void);
	deSynchObject *		GetSynchObject(void)			  { return &m_SynchObject; }	
	deNetUser *			GetOwner( void );

#ifdef DN_SESSION_TIME_INT64
	s64					GetAvgLag(void);
#else
	float				GetAvgLag(void);
#endif

	const deConnectionDesc *  GetConnDesc(void)			  { return &m_ConnectionDesc; }

	static DWORD		GetMaxPacketSize(void)			  { return m_MaxPacketSize; }

protected:

	virtual eNetError	OnAttemptReset( DWORD dwFlags = NULL )						= 0;
	virtual eNetError	OnBindAsServer( DWORD dwFlags = NULL )						= 0;
	virtual eNetError	OnConnectTo( deNetAddress * pAddress )						= 0;
	virtual eNetError	OnSend( WORD pNetMsgID, const void * pBuff, DWORD iSize, DWORD dwFlags )	= 0;	
	virtual eNetError	OnDisconnect( DWORD dwFlags = NULL )						= 0;

public:

	// used for qsort()
	static int CompareConnections( const void *arg1, const void *arg2 );

	struct deConfirmedReciept
	{
		int			ID;
		int			iSize;
		BYTE *		buffer;
		float		fTimeSent;
		float		fMaxTime;
	};

	struct dePartialReciept
	{
		int		ID;
		int		iSize;
		BYTE *	buffer;
		int		iIndex;
		int		iTotalPackets;		
	};	

protected:

	eType				m_Type;
	deConnectionDesc	m_ConnectionDesc;
	
private:

	deSynchObject		m_SynchObject;
	deConnectionBin	*	m_ParentConnectionBin;
	aPacketLists		m_aPacketLists;
	deNetUser *			m_Owner;
	bool				m_bIsReady;
	DWORD				m_dwDesc;

#ifdef DN_SESSION_TIME_INT64
	s64					m_LagHistory[4];
	s64					m_AvgLag;
#else
	float				m_LagHistory[4];
	float				m_AvgLag;
#endif

	static DWORD		m_MaxPacketSize;

} deConnection, *pdeConnection;

#endif