#ifndef __PDAC__
#define __PDAC__

#include <exception>
#include <string>
#include <list>
#include <map>

#include <parsec/pdp_common.h>
#include <parsec/parsec_aud.h>

namespace PDAC
{

using namespace std;

#ifndef DEFAULT_CONFIG_RULES_PATH
#define DEFAULT_CONFIG_RULES_PATH "/etc/parsec/PDAC/rules.cfg"
#endif

#ifndef DEFAULT_CONFIG_DEVICES_PATH
#define DEFAULT_CONFIG_DEVICES_PATH "/etc/parsec/PDAC/devices.cfg"
#endif

class Rule;
typedef list<string> StringList;
typedef map<string,Rule*> MapRules;

//******************************************************************************

class Exception : public exception
{
public:

	Exception() throw();
	Exception( const string & /*message*/ ) throw();
	Exception( const Exception& /*ex*/ ) throw();
	virtual ~Exception() throw();
	Exception& operator= ( const Exception& /*ex*/ ) throw();
	virtual const char* what() const throw();

protected :

	string _message;

};

//******************************************************************************
class ItemConst
{
public:
//	virtual ~ItemConst(); /* 4 proper cleanup */

	virtual bool isEnabled() const = 0;
	virtual const string &name() const = 0;
	virtual const string &description() const = 0;
	virtual const StringList &expressions() const = 0;

	void writeExpressions(ostream& os) const;
};

class Item: public virtual ItemConst
{
public:
	Item();
	virtual ~Item() {};

	bool isEnabled() const;
	void setEnabled(bool isEnabled);

	const string &name() const;
	void setName( const string & /*name*/ );

	const string &description() const;
	void setDescription(const string &description);

	StringList &expressions();
	const StringList &expressions() const;

protected:

	bool _isEnabled;

	string _name;
	string _description;

	StringList _expressions;

};
//******************************************************************************
typedef ItemConst RuleConst;

class Rule: public Item
{
	friend class RulesFile;
};
//******************************************************************************
class DevConst: public virtual ItemConst
{
public:
//	virtual ~DevConst(); /* 4 proper cleanup */

	virtual const string &user() const = 0;
	virtual const string &group() const = 0;
	virtual int mode() const = 0;

///??? PDPL eatreference

	virtual const PDPL_T* label() const = 0;
	virtual string labelToString() const = 0;

	virtual PDP_LEV_T getLev() const = 0;
	virtual PDP_ILEV_T getILev() const = 0;
	virtual PDP_CAT_T  getCat() const = 0;
	virtual PDP_TYPE_T getType() const = 0;

	virtual uint32_t succAudit() const = 0;
	virtual uint32_t failAudit() const = 0;

	virtual const StringList &rules() const = 0;

	void validate() const;
	void writeUdevRuleHeader(ostream &os) const;
	void writeUdevRuleFooter(ostream &os) const;
};

class Dev: public Item, public DevConst
{
	friend class DevicesFile;

public:

	Dev();
	Dev( const Dev & /*devicePDAC*/ );
	virtual ~Dev();

	const Dev &operator=( const Dev & /*devicePDAC*/ );

	const string &user() const;
	void setUser(const string &user);

	const string &group() const;
	void setGroup(const string &group);

	int mode() const;
	void setMode( int mode );

	const PDPL_T* label() const;
	string labelToString() const;

	PDP_LEV_T getLev() const;
	PDP_ILEV_T getILev() const;
	PDP_CAT_T  getCat() const;
	PDP_TYPE_T getType() const;

	void setLev( PDP_LEV_T /*lev*/ );
	void setILev( PDP_ILEV_T /*iLev*/ );
	void setCat( PDP_CAT_T /*cat*/ );
	void setType( PDP_TYPE_T /*type*/ );

	uint32_t succAudit() const;
	uint32_t failAudit() const;

	void setSuccAudit( uint32_t /*succ*/ );
	void setFailAudit( uint32_t /*fail*/ );

	StringList &rules();
	const StringList &rules() const;

protected:

	string _owner;
	string _group;

	int _mode;
	PDPL_T *_pdpLabel;
	parsec_audit_t _audit;

	StringList _rules;

};

} /* namespace PDAC */

#endif /* __PDAC__ */
