#ifndef DATA_H
#define DATA_H

#include <winsock2.h>
#include <string>
#include <vector>
#include "smartptr.h"
#include "util.h"

struct SAnnotation
{
	size_t index;
	std::string annotation;
};

struct SCoding
{
	uint64 nTot;
	uint32 nLow;
	uint32 nSym;
};

inline bool operator ==( const SCoding& a, const SCoding& b )
{
	return a.nTot == b.nTot && a.nLow == b.nLow && a.nSym == b.nSym;
}

inline bool operator !=( const SCoding& a, const SCoding& b )
{
	return !operator==(a,b);
}

struct SSessionID
{
	SSessionID() { for (int i=0; i<ID_LENGTH; i++) id[i] = 0; }
	static const int ID_LENGTH = 64;
	uint8 id[ID_LENGTH];

	bool operator==(const SSessionID& rhs) const
	{
		return 0 == memcmp(id, rhs.id, ID_LENGTH);
	}
};

struct SPacket : public _reference_target_multithread_t
{
	SSessionID session;
	uint32 uniqueId;
	bool isEncoding;
	int32 channel;
	std::vector<SCoding> coding;
	std::vector<SAnnotation> annotations;
	ULONG senderAddress;
};

typedef _smart_ptr<SPacket> SPacketPtr;

struct SSessionHeader
{
	SSessionID id;
	uint32 numPackets;
};

void ReadSock( Socket& sock, uint8& value );

template <class T>
void ReadSock( Socket& sock, T& value )
{
	uint8 * pVal = (uint8*)&value;
	for (int i=0; i<sizeof(value); i++)
		ReadSock( sock, pVal[i] );
}

void ReadSock( Socket& sock, std::string& value );

template <class T>
void ReadSock( Socket& sock, std::vector<T>& value )
{
	uint32 size;
	ReadSock(sock, size);
	if (size > 1000000)
		throw std::runtime_error("size too big");
	value.resize(0);
	for (uint32 i=0; i<size; i++)
	{
		T temp;
		ReadSock(sock, temp);
		value.push_back(temp);
	}
}

void ReadSock( Socket& sock, SAnnotation& annot );
void ReadSock( Socket& sock, SPacket& annot );

#endif
