///////////////////////////////////////////////////////////////////////////////
/// @file dePacket.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	_DEPACKET_HPP
#define _DEPACKET_HPP

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

#ifndef		_DENETMSG_HPP
 #include	"deNetMsg.hpp"
#endif

class DENET_API	dePacket
{
public:

	// packet flags
	enum eFlag
	{
		PACKET_SEND_RECP_CONFIRMATION	=	0x01,
		PACKET_FRAGMENT_BEGIN			=	0x02,
		PACKET_FRAGMENT_END				=	0x04,
		PACKET_FRAGMENT					=	0x06, // (0x2|0x4)
	};

	// public packet header 
	struct PacketHeader
	{
		hNetUser	Recipient;
		BYTE		Type;
		BYTE		Flags;

		union
		{
			struct
			{
				hNetUser	Sender;
				WORD		LocalID;
			};

			DWORD			ID;
		};
		WORD		NetMsgID;
		WORD		SubID;
		DWORD		Size;
		DWORD		TotalSize;
	};

	dePacket(void);
	dePacket( const BYTE * pData, DWORD dwFlags = NULL );
	dePacket( const PacketHeader& pHeader, const void * m_Data, DWORD dwFlags = NULL );
	virtual ~dePacket(void);

	bool				NeedRecvConfirmation(void)	const { return m_Header.Flags & dePacket::PACKET_SEND_RECP_CONFIRMATION != 0; }
	bool				IsFragmented(void)			const { return m_Header.Flags & dePacket::PACKET_FRAGMENT != 0; }
	BYTE *				GetData(void)				const { return m_Data; }
	const PacketHeader&	GetHeader(void)				const { return m_Header; }

	static dePacket *	SortPackets( dePacket * pPackets, int iNumPackets );
	static dePacket *	ConsolidatePackets( const dePacket * pPackets, int iNumPackets );
	
protected:

	BYTE *			m_Data;
	PacketHeader	m_Header;
	
public:

	static int ComparePacket( const void * l, const void * r );
	friend bool operator !=		( const dePacket& l, const dePacket& r ) {	return ( l.m_Header.ID != r.m_Header.ID );  }
	friend bool operator ==		( const dePacket& l, const dePacket& r ) {	return ( l.m_Header.ID == r.m_Header.ID );  }
	friend bool operator >		( const dePacket& l, const dePacket& r ) {	if( l.m_Header.ID == r.m_Header.ID ) return l.m_Header.SubID >  r.m_Header.SubID; else return l.m_Header.ID > r.m_Header.ID;  }
	friend bool operator <		( const dePacket& l, const dePacket& r ) {	if( l.m_Header.ID == r.m_Header.ID ) return l.m_Header.SubID <  r.m_Header.SubID; else return l.m_Header.ID < r.m_Header.ID;  }
	dePacket& operator =		( const dePacket& r );
};

#endif