#ifndef ATTRIBUTESET
#define ATTRIBUTESET

#include <string>
#include <set>

typedef char Attribute;

/**
 * An AttributeSet simply represents a set of Attributes.
 */
class AttributeSet
{
	public:
		/**constructs an empty AttributeSet*/
		AttributeSet();
		
		/**constructs an AttributeSet consisting of a single attribute*/
		AttributeSet(const Attribute& attribute);

		/**
		 * Constructs an AttributeSet from a textual representation
		 * @see setFromText
		 */
		AttributeSet(const std::string& textualRepresentation);

		virtual ~AttributeSet();

		/**
		 * (Re-) Initializes an AttributeSet from a textual representation (e.g. A,B,C)
		 * @param textualRepresentation the textual representation of the attribute set
		 */
		void setFromText(const std::string& textualRepresentation);

		/**
		 * Adds all entries of another AttributeSet to the current one.
		 * @param another the AttributeSet from which the entries should be retrieved
		 * @return true if at least one new entry has been added to the current set, false otherwise
		 */
		bool add(const AttributeSet& another);

		/**
		 * Removes a single attribute from the current AttributeSet
		 * @param attr the Attribute to remove
		 */
		void substract(const Attribute& attr);

		/**
		 * Indicates whether a AttributeSet is empty (has no single attribute in it)
		 * @return true if there is no attribute in the set, false otherwise
		 */
		bool empty() const;

		/**
		 * Checks whether the current attribute set is equal to another one. Two AttributeSets
		 * are considered equal if their both contain the other set.
		 * @param that the AttributeSet to compare the current set to
		 * @return true if both sets are equal, false otherwise
		 */
		bool operator==(const AttributeSet& that) const;

		/**
		 * The Iterator can be used to iterate over the single attributes stored in an AttributeSet.
		 */
		class Iterator{
			public:
				Iterator(const std::set<Attribute>::const_iterator& element);
				virtual ~Iterator();

				/**
				 * Retrieves the current Attribute the iterator points to. Must only be called on a
				 * valid iterator instance (e.g. not AttributeSet::end).
				 * @return the Attribute the iterator points to
				 */
				Attribute operator*();

				/**
				 * Increments the current iterator position by one.
				 */
				void operator++();

				/**
				 * Checks whether two iterators point at the same position in an AttributeSet.
				 * param that the iterator to compare the current iterator with
				 * @return true if the two iterators point at the same position, false otherwise
				 */
				bool operator==(const AttributeSet::Iterator& that);

				/**
				 * Checks whether two iterators point at different positions in an AttributeSet.
				 * param that the iterator to compare the current iterator with
				 * @return true if the two iterators point at different positions, false otherwise
				 */
				bool operator!=(const AttributeSet::Iterator& that);

			private:
				std::set<Attribute>::const_iterator theElement; //interal iterator representation
		};

		/**
		 * Returns an iterator pointing to the first element in the set (if any).
		 * @return a corresponding iterator
		 */
		Iterator begin() const;
		
		/**
		 * Returns an iterator pointing after the last element in the set.
		 * @return a corresponding (invalid) iterator
		 */
		Iterator end() const;

		/**
		 * Converts the AttributeSet to a printable representation.
		 * @return a printable representation
		 */
		std::string getText() const;

		/**
		 * Checks whether the AttributeSet contains all Attributes found in another set.
		 * @param anotherSet the AttributeSet to retrieve the Attributes from
		 * @return true if the AttributeSet contains all Attributes, false otherwise
		 */
		bool contains(const AttributeSet& anotherSet) const;

		/**
		 * Checks whether the AttributeSet contains a single attribute.
		 * @param attr the Attribute to look for
		 * @return true if the AttributeSet contains the attribute, false otherwise
		 */
		bool contains(const Attribute& attr) const;

	private:
		std::set<Attribute> theAttributes; //internal representation
};

#endif
