#ifndef DATAQUEUE_H
#define DATAQUEUE_H

template< int maxItems, int maxBuffer >
class idDataQueue
{
public:
	idDataQueue()
	{
		dataLength = 0;
	}
	bool Append( int sequence, const byte* b1, int b1Len, const byte* b2 = NULL, int b2Len = 0 );
	void RemoveOlderThan( int sequence );
	
	int GetDataLength() const
	{
		return dataLength;
	}
	
	int Num() const
	{
		return items.Num();
	}
	int ItemSequence( int i ) const
	{
		return items[i].sequence;
	}
	int ItemLength( int i ) const
	{
		return items[i].length;
	}
	const byte* ItemData( int i ) const
	{
		return &data[items[i].dataOffset];
	}
	
	void Clear()
	{
		dataLength = 0;
		items.Clear();
		memset( data, 0, sizeof( data ) );
	}
	
private:
	struct msgItem_t
	{
		int		sequence;
		int		length;
		int		dataOffset;
	};
	idStaticList<msgItem_t, maxItems > items;
	int		dataLength;
	byte	data[ maxBuffer ];
};

/*
========================
idDataQueue::RemoveOlderThan
========================
*/
template< int maxItems, int maxBuffer >
void idDataQueue< maxItems, maxBuffer >::RemoveOlderThan( int sequence )
{
	int length = 0;
	while( items.Num() > 0 && items[0].sequence < sequence )
	{
		length += items[0].length;
		items.RemoveIndex( 0 );
	}
	if( length >= dataLength )
	{
		assert( items.Num() == 0 );
		assert( dataLength == length );
		dataLength = 0;
	}
	else if( length > 0 )
	{
		memmove( data, data + length, dataLength - length );
		dataLength -= length;
	}
	length = 0;
	for( int i = 0; i < items.Num(); i++ )
	{
		items[i].dataOffset = length;
		length += items[i].length;
	}
	assert( length == dataLength );
}

/*
========================
idDataQueue::Append
========================
*/
template< int maxItems, int maxBuffer >
bool idDataQueue< maxItems, maxBuffer >::Append( int sequence, const byte* b1, int b1Len, const byte* b2, int b2Len )
{
	if( items.Num() == items.Max() )
	{
		return false;
	}
	if( dataLength + b1Len + b2Len >= maxBuffer )
	{
		return false;
	}
	msgItem_t& item = *items.Alloc();
	item.length = b1Len + b2Len;
	item.sequence = sequence;
	item.dataOffset = dataLength;
	memcpy( data + dataLength, b1, b1Len );
	dataLength += b1Len;
#ifdef __GNUC__
#if __GNUC_PREREQ(13, 0)
	if (b2 != __null) {
#endif
#endif
		memcpy( data + dataLength, b2, b2Len );
#ifdef __GNUC__
#if __GNUC_PREREQ(13, 0)
	}
#endif
#endif
	dataLength += b2Len;
	return true;
}

#endif // DATAQUEUE_H
