#ifndef FILTER_H
#define FILTER_H

#include "ProtocolInfo.h"
#include <list>

enum EFilterMatch { EFilterMatch_None, EFilterMatch_Receiver, EFilterMatch_Sender };

class FilterSet;

class Filter 
{
public:
	Filter();
	Filter(const Filter & src);
	virtual ~Filter();
	virtual Filter * Clone() const = 0;
	virtual bool Match(const ProtocolInfoElement * pProtocolInfo) = 0;
	EFilterMatch GetMatchType() const;
	void AddNextLayerFilter(const Filter & filter);
	void ClearNextLayerFilters();
	FilterSet * DetachFilterSet();
	virtual std::string GetSourcePcapFilter() const;
	virtual std::string GetDestinationPcapFilter() const;
	void SetAllPacketsAccepted(bool bAccept);
	bool AreAllPacketsAccepted();
	friend class FilterSet;
protected:
	void SetMatchType(EFilterMatch matchType);
private:
	EFilterMatch m_matchType;
	FilterSet * m_pNextLayer;
	bool m_bAcceptAll;
};

class FilterSet : std::list<Filter *>
{
public:
	FilterSet();
	FilterSet(const FilterSet & src);
	~FilterSet();
	void AddFilter(const Filter & filter);
	bool Match(const ProtocolInfoElement * pProtocolInfo);
	void MoveToNextLayer();
	std::string GetPcapFilter() const;
protected:
	void SetMatchType(EFilterMatch matchType);
	friend class Filter;
};

class ComponentFilter : std::list< std::pair <const t3devlib::ComponentId *, FilterSet *> >
{
public:
	ComponentFilter();
	ComponentFilter(const ComponentFilter & src);
	~ComponentFilter();
	void RegisterComponent(const t3devlib::ComponentId * pId, const FilterSet & pFilter);
	void UnregisterComponent(const t3devlib::ComponentId * pId);
	void Clear();
	bool Match(const ProtocolInfoElement * pProtocolInfo);
	void MoveToNextLayer();
	void EnqueueMessage(const unsigned char * pData, int nDataLength);
	std::string GetPcapFilter() const;
private:
	void RegisterItem(const t3devlib::ComponentId * pId, const FilterSet & filter);
};

#endif
