#include "munga.h"
#include "set.h"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//
//#############################################################################
// Set
//#############################################################################
//
Set::Set(Node *node):
	 Socket(node),
	 contents(NULL)
{

}




//
//#############################################################################
// ~Set
//#############################################################################
//
Set::~Set()
{
	SetReleaseNode(NULL);
	if (contents)
	{
		delete contents;
	}
}

//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
	Set::TestInstance() const
{
	Socket::TestInstance();
	Check(contents);
	return True;
}


//
//#############################################################################
// Union
//
// Merge contents of this with rhs.   Items that occur in either set are placed
// in the resulting set, with no duplication.  It is assumed that both operands
// are proper sets, ie. they contain no duplicates.
//#############################################################################
//

Set
	Set::Union(const Set &) const
{
	Check(this);


	Set result(NULL);

	return result;
}


//
//#############################################################################
// Intersection
//
// Merge contents of this with rhs.   Items that occur in both sets are placed
// only once in the resulting set.  It is assumed that both operands are proper
// sets, ie. they contain no duplicates.
//
// This implementation of set intersection is dumb and slow.
//#############################################################################
//

Set
	Set::Intersection(const Set &rhs) const
{
	Check(this);
	Check(rhs);

	// Contents iterator is a SetIterator and not a ChainIterator in order to
	// have access to the ChainIterator::ReadAndNextImplentation.
	// We circumvent encapsulation protections by declaring Set a friend of SetIterator
	// (which derives from ChainIterator).  Set is not a friend of ChainIterator.

	SetIterator contents_iterator(contents);

	// Casting away const is safe since our local iterator is not going to insert or
	// remove items from rhs.
	SetIterator rhs_iterator((Set *) &rhs);
	Plug *lhs_plug;
	Plug *rhs_plug;
	Set result(NULL);


	while ((lhs_plug = Cast_Object(Plug *, contents_iterator.ReadAndNextImplementation())) != NULL)
	{
		while ((rhs_plug = Cast_Object(Plug *,rhs_iterator.ReadAndNextImplementation())) != NULL)
		{
			if (lhs_plug == rhs_plug)
			{
				result.AddImplementation(lhs_plug);
			}
		}
	}
	return result;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//
//#############################################################################
// SetIterator
//#############################################################################
//
SetIterator::SetIterator(Set *set):
	ChainIterator(set->contents)
{
	Check(set);
}

SetIterator::SetIterator(const SetIterator &iterator):
	ChainIterator(Cast_Object(Chain*, (Cast_Object(Set *,iterator.socket)->contents)))
{
	Check(&iterator);
}

SetIterator::SetIterator(Chain *chain):
	ChainIterator(chain)
{
	Check(chain);
}

SetIterator::~SetIterator()
{
}
