#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, // 0
	EProtocolType_Unknown, // 1
	EProtocolType_Ethernet, // 2
	EProtocolType_IPv4,  // 3
	EProtocolType_IPv6,  // 4
	EProtocolType_Udp, // 5
	EProtocolType_Tcp, // 6
	EProtocolType_Sip, // 7
	EProtocolType_Dns // 8
};

class ProtocolInfoElement 
{
protected:
	ProtocolInfoElement();
public:
	virtual ~ProtocolInfoElement();
	virtual EProtocolType GetId() const = 0;
	virtual bool Match(const ProtocolInfoElement & toCompare) const;
	virtual ProtocolInfoElement * Clone() const = 0;
	virtual std::string ToString() 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;
	virtual std::string ToString() const { return std::string("IPv4Info"); }
 };

class IPv6Info : public ProtocolInfoElement
{
private:
	std::vector<unsigned char> m_nSrcAddr, m_nDstAddr;
	std::string m_sSrcAddr, m_sDstAddr;
public:
	IPv6Info();
	IPv6Info(const IPv6Info & src);
	virtual ~IPv6Info();
	virtual EProtocolType GetId() const { return EProtocolType_IPv6; }
	virtual bool Match(const ProtocolInfoElement & toCompare) const;
	std::string GetSourceAddress() const { return m_sSrcAddr; }
	std::string GetDestinationAddress() const { return m_sDstAddr; }
	void SetSourceAddress(std::string sAddr) { m_sSrcAddr = sAddr; }
	void SetDestinationAddress(std::string sAddr) { m_sDstAddr = sAddr; }
	virtual ProtocolInfoElement * Clone() const;
	virtual std::string ToString() const { return std::string("IPv6Info"); }
 };

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; }
	virtual std::string ToString() const { return std::string("TransportLayerInfo"); }
 };

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

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

#endif
