#include "attributeset.hh"
#include <sstream>
#include <iostream>

AttributeSet::AttributeSet(){}

AttributeSet::AttributeSet(const std::string& textualRepresentation)
{
	setFromText(textualRepresentation);
}

AttributeSet::AttributeSet(const Attribute& attribute)
{
	std::stringstream stream;
	stream<<attribute;
	setFromText(stream.str()); //use filtering code in setFromText
}

void AttributeSet::setFromText(const std::string& textualRepresentation)
{
	theAttributes.clear(); //clear potential previous content
	std::string expectedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	std::string::size_type result = textualRepresentation.find_first_of(expectedChars);
	while(result!=std::string::npos)
	{
		theAttributes.insert(textualRepresentation.at(result)); //add current Attribute
		result = textualRepresentation.find_first_of(expectedChars, result+1); //find next
	}
}

bool AttributeSet::add(const AttributeSet& another)
{
	bool result = false;
	for(std::set<Attribute>::const_iterator cit = another.theAttributes.begin(); 
			cit!=another.theAttributes.end(); ++cit)
	{
		if(theAttributes.insert(*cit).second)
			result = true; //set to true if new item was inserted (second value in return pair)
	}
	return result;
}

void AttributeSet::substract(const Attribute& attr)
{
	theAttributes.erase(attr);
}

bool AttributeSet::empty() const
{
	return theAttributes.empty();
}

bool AttributeSet::operator==(const AttributeSet& that) const
{
	return (contains(that) && that.contains(*this));
}


AttributeSet::Iterator::Iterator(const std::set<Attribute>::const_iterator& element) :
	theElement(element){}
AttributeSet::Iterator::~Iterator(){}

Attribute AttributeSet::Iterator::operator*()
{
	return *theElement;
}

void AttributeSet::Iterator::operator++()
{
	++theElement;
}

bool AttributeSet::Iterator::operator==(const AttributeSet::Iterator& that)
{
	return theElement==that.theElement;
}

bool AttributeSet::Iterator::operator!=(const AttributeSet::Iterator& that)
{
	return !(*this==that);
}

AttributeSet::Iterator AttributeSet::begin() const
{
	return Iterator(theAttributes.begin());
}

AttributeSet::Iterator AttributeSet::end() const
{
	return Iterator(theAttributes.end());
}

AttributeSet::~AttributeSet(){}

std::string AttributeSet::getText() const
{
	std::stringstream result;
	for(std::set<Attribute>::const_iterator cit=theAttributes.begin();
		cit!=theAttributes.end(); ++cit)
	{
		result<<*cit; //add current Attribute
	}
	return result.str();
}

bool AttributeSet::contains(const Attribute& attr) const
{
	bool result = false;
	for(std::set<Attribute>::const_iterator cit = theAttributes.begin();
			cit != theAttributes.end(); ++cit)
	{
		if(*cit==attr)
		{
			result = true;
			break;
		}
	}
	return result;
}


bool AttributeSet::contains(const AttributeSet& anotherSet) const
{
	bool result = false;
	for(std::set<Attribute>::const_iterator theirSet = anotherSet.theAttributes.begin();
			theirSet!=anotherSet.theAttributes.end(); ++theirSet)
	{
		result = false;
		for(std::set<Attribute>::const_iterator ourSet=theAttributes.begin(); 
				ourSet!=theAttributes.end(); ++ourSet)
		{
			if(*ourSet == *theirSet) //dereference iterators and check for equality of Attributes
			{
				result = true; //we found a match
				break; //exit inner loop, skip upcoming Attributes as we already found our match
			}
		}
		if(!result)
		{
			//we did not find our attribute, so we do not contain this particular attribute, leave
			break; //exit outer loop, returning false
		}
	}
	return result;
}



