//! Base object class
class Object {
// Construction and destruction
public:
	Object();
	Object(Object *parent, const std::string &name);
	virtual ~Object();
private:
	Object(const Object&);                     //!< Copying Forbidden
	Object& operator=(Object&);                //!< Assigning forbidden

// Internal data
private:
	Object *m_parent;                          //!< Parent object
	const std::string m_name;                  //!< Name of this object
	std::vector<Object*> m_children;           //!< Children

public:
// Accessors
	std::string getName()            const;    //!< Name of the object
	Object*     getParent()          const;    //!< Get the parent object
	uint32_t    getChildCount()      const;    //!< Number of children
	Object*     getChild(uint32_t n) const;    //!< Get child [n]

	void setName(const std::string&);          //!< Rename the object
	void setParent(Object *newParent);         //!< Change the parent
	void addChild(Object *child);              //!< Add new child

// Operations/Tasks
	virtual uint8_t getOperCount() const;      //!< Num oper's available
	virtual std::string getOper(uint8_t n);    //!< Get operation's name
	virtual void doOper(const std::string &oper); //!< Perform operation
};

//! One list element [Abstract]
class ListNode {

// Construction and destruction
public:
	ListNode();
	ListNode(List *parent, uint8_t fieldCount);
	virtual ~ListNode();
private:
	ListNode(const ListNode&);                 //!< Copying forbidden
	ListNode& operator=(ListNode&);            //!< Assigning forbidden

// Internal data
private:
	List*   m_parent;                          //!< Parent list
	uint8_t m_fieldCount;                      //!< Number of fields

public:
// Accessors
	List*       getParent()         const;     //!< Parent list
	uint8_t     getFieldCount()     const;     //!< Number of fields
	virtual std::string getField(uint8_t n) const = 0;

	void setParent(List *newParent);
	void setFieldCount(uint8_t n);
	virtual void setFieldData(uint8_t field, const std::string &data) = 0;

// Operations
	virtual uint8_t getOperCount();
	virtual std::string getOper(uint8_t n);
	virtual void doOper(const std::string &oper);
};

//! List containing any number of ListNode objects
class List : public Object {

// Construction and destruction
public:
	List();
	List(
		Object *parent, const std::string &name, uint8_t fieldcount,
		std::vector<std::string> fieldnames
	);
	~List();
private:
	List(const List&);                         //!< Copying forbidden
	List& operator=(List&);                    //!< Assigning forbidden

// Internal data
private:
	std::vector<std::string> m_fieldNames;    //!< List header data
	std::vector<ListNode*>   m_nodes;         //!< List elements

// Accessors
public:
	uint8_t     getFieldCount()         const;
	std::string getFieldName(uint8_t n) const;
	uint8_t     getSize()               const;
	ListNode*   getNode(uint32_t n)     const;
};

/**
	This is what I intend to achieve with the system:

	Root
	  +-- Object
	  +-- Object
	  +-- List
	  |     |-- ListNode
	  |     |-- ListNode
	  |     +-- ListNode
	  |
	  +-- List
	  |     |-- ListNode
	  |     +-- ListNode
	  |
	  +-- Object
	  |     |-- Object
	  |     |-- Object
	  |     |     +- List
	  |     |          +- ListNode
	  |     +-- Object
	  +-- Object


	If you  substute List to  `Directory` and  ListNode to a file, you
	get pretty standard file-system-like tree.

	One  interesting point  is that Object may  both be a `file` and a
	`directory` - depending on if it has children or not.

	ListNode isn't allowed to have children. It's basically a degraded
	object - it has parents, but it can no longer have children of its
	own.

	Thus:

	HydraNode
	   +-- MetaDb
	   |      +-- MetaData
	   |      |      +-- File Size
	   |      |      +-- Modification date
	   |      |      +-- File Names
	   |      |      |       |-- FileName[0]
           |      |      |       |-- FileName[1]
	   |      |      |       |-- FileName[2]
	   |      |      +-- HashSets
	   |      |      |       +-- ED2K
	   |      |      |       |    + PartSize (9728000)
	   |      |      |       |    + FileHash
	   |      |      |       |    + PartHashes
	   |      |      |       |          + PartHash[0]
	   |      |      |       |          + PartHash[1]
	   |      |      |       |          + PartHash[2]
	   |      |      |       +-- SHA1
	   |      |      |            + PartSize (0)
	   |      |      |            + FileHash
	   |      |      +-- AudioMetaData
	   |      |               + Title
	   |      |               + Album
	   |      |               + Performer
	   |      +-- MetaData
	   |             + File Size
	   |             ...
	   |      ...
	   +-- SharedFilesList
	   |       +-- SharedFile
	   |       |       +-- FileSize
	   |       |       +-- PartData
	   |       |              +-- PartData
	   |       |                     +-- Completed
	   |       |                     +-- Verified
	   |       +-- SharedFile
	   |           ...
	   +-- Modules
	         +-- ED2K
		 |     +-- ServerList
		 |     |        +-- Server
		 |     |        |     +-- IP
		 |     |        |     +-- Port
		 |     |        +-- Server
		 |     +-- CreditsDb
		 |              +-- ClientCredits
		 |              |        +-- Uploaded
		 |              |        +-- Downloaded
		 |              |        +-- Hash
		 |              |        +-- PubKey
		 |              +-- ClientCredits
		 |                       ...
		 +-- BitTorrent
		 |      +-- ...
		 +-- gnutella
		 |      +-- ...
		 +-- ...


*/