#ifndef PROTOCOL_INFO_H
#define PROTOCOL_INFO_H

#include <list>
#include <vector>

#ifdef DISPATCH_DEBUG
// TODO: For debugging only !!!
namespace t3devlib
{
	typedef int ComponentId;
}
#else
#include <t3devlib/t3devlib.h>
#endif

enum EProtocolType 
{ 
	EProtocolType_None,
	EProtocolType_Unknown,
	EProtocolType_Ethernet,
	EProtocolType_IPv4, 
	EProtocolType_Udp,
	EProtocolType_Tcp,
	EProtocolType_Sip,
	EProtocolType_Dns
};

class ProtocolInfoElement 
{
protected:
	ProtocolInfoElement();
public:
	virtual ~ProtocolInfoElement();
	virtual EProtocolType GetId() const = 0;
	virtual bool Match(const ProtocolInfoElement & toCompare) const;
	virtual ProtocolInfoElement * Clone() const = 0;
};

class ProtocolInfo : private std::vector<ProtocolInfoElement *>
{
public:
	ProtocolInfo();
	~ProtocolInfo();
	void AddItem(ProtocolInfoElement * info);
	size_t Count();
	const ProtocolInfoElement * operator[] ( int nIndex ) const;
    bool Match(ProtocolInfo & info) const;
};

class IPv4Info : public ProtocolInfoElement
{
private:
	unsigned int m_nSrcAddr, m_nDstAddr;
public:
	IPv4Info();
	IPv4Info(const IPv4Info & src);
	virtual ~IPv4Info();
	virtual EProtocolType GetId() const { return EProtocolType_IPv4; }
	virtual bool Match(const ProtocolInfoElement & toCompare) const;
	unsigned int GetSourceAddress() const { return m_nSrcAddr; }
	unsigned int GetDestinationAddress() const { return m_nDstAddr; }
	void SetSourceAddress(unsigned int nAddr) { m_nSrcAddr = nAddr; }
	void SetDestinationAddress(unsigned int nAddr) { m_nDstAddr = nAddr; }
	virtual ProtocolInfoElement * Clone() const;
 };

class TransportLayerInfo : public ProtocolInfoElement
{
private:
	unsigned short m_nSrcPort, m_nDstPort;
protected:
	TransportLayerInfo();
	TransportLayerInfo(const TransportLayerInfo & src);
public:		
	virtual ~TransportLayerInfo();
	virtual bool Match(const ProtocolInfoElement & toCompare) const;
	unsigned short GetSourcePort() const { return m_nSrcPort; }
	unsigned short GetDestinationPort() const { return m_nDstPort; }
	void SetSourcePort(unsigned short nPort) { m_nSrcPort = nPort; }
	void SetDestinationPort(unsigned short nPort) { m_nDstPort = nPort; }
 };

class TcpInfo : public TransportLayerInfo
{
public:
	TcpInfo();
	TcpInfo(const TcpInfo & src);
	virtual ~TcpInfo();
	virtual EProtocolType GetId() const { return EProtocolType_Tcp; }
	virtual ProtocolInfoElement * Clone() const;
};

class UdpInfo : public TransportLayerInfo
{
public:
	UdpInfo();
	UdpInfo(const UdpInfo & src);
	virtual ~UdpInfo();
	virtual EProtocolType GetId() const { return EProtocolType_Udp; }
	virtual ProtocolInfoElement * Clone() const;
};

#endif
