// © Copyright 1995. Joseph Bergin. All rights reserved.

#ifndef __Dictionary__
#define __Dictionary__

#include <iostream.h>
#include "Set.h"
#include "Association.h"
#include "Boolean.h"

// A Dictionary is a set of associations.  As such it represents
// a finite function.  They can be used as the basis of simple databases.  

// Value is required to have a default constructor. 

template<class Key, class Value>
class Dictionary:public Set<Association<Key,Value> >
{	public:
	// constructors
		Dictionary():Set<Association<Key,Value> >(){}
//		Dictionary(Dictionary &d):Set<Association<Key,Value> >(d){};
	// destructor
//		~Dictionary(){}
	// assignment
		// INHERITED SERVES		
/*		Dictionary & operator = ( Dictionary &d)
		{	if(this != &d)
			{	_cardinality = 0;
				for(int i = 0; i<= d._cardinality; i++)
					Set<Association<Key,Value> >::insert(d._elements[i]);
				cout <<"test= "<<_cardinality<<endl;
			}
			return *this;
		}
*/		
		void atPut(const Key & k, const Value & v) 
		// insert a new association (removing an existing one with same key).
		{	if(element(k))
				remove(k);
			Set<Association<Key,Value> >::insert(Association<Key,Value>(k,v));
				// This uses the inhereited insert. 
		}
		
		Boolean at(const Key &k, Value &v) 
		// Set v to be the associated value if any. Return true if v was set.
		{	Association<Key,Value> * a;
			if(find(k, a)) 
			{	v = a->_value;
				return true;
			}	
			return false;
		}

		Value & operator[](const Key & k) // Combines at and atPut.  
		{	static Value dummy;
			Association<Key,Value> *a;
			if(find(k,a))
			{	return a->_value;
			}
			return dummy;
		}
		
		Boolean element(const Key & k) // Is this key stored?
		{	for(int i = 0; i< _cardinality; i++)
				if (Association<Key,Value>(_elements[i]).key() == k) return true;
			return false;
		}
		
		void remove(const Key& k) // Remove any association with this key. 
		{	Association<Key,Value>* a;
			if(find(k, a)) 
			{	Set<Association<Key,Value> >::remove(*a);
			}
		};
		
		void insert(const Association<Key,Value> & a) 
		//Does NOT insert this actual association, but an equivalent one instead. 
		{	Key k = a.key();
			Value v = a.value();
			atPut(k,v);
		};
		
	private:
/*		Association<Key,Value> newAssociation(Key k,Value v)
		{	Association<Key,Value> result(k,v);
			return result;
		}
*/		
		Boolean find(const Key & k, Association<Key,Value>* &a)
		{	for(int i = 0; i< _cardinality; i++)
			{	if (Association<Key,Value>(_elements[i]).key() == k)
				{	a = &_elements[i];
					return true;
				}
			}
			return false;
		}

//	friend void saveDictionary(ostream& os, const Dictionary<Key,Value>& D);
//	friend void restoreDictionary(istream& is, Dictionary<Key,Value>& D);

};

// Requires an output operator << for both key and value.
template <class Key, class Value>
void saveDictionary (ostream &os, const Dictionary<Key,Value> D)
{  int len = D.cardinality();
	os<< len <<endl;
	Array<Association<Key,Value> > elements = D.asArray();
	for(int i = 0; i < len; i++)
		os <<elements[i].key()<<endl
			<<elements[i].value()<<endl;
}

// Requires a default constructor and an input operator>> for both key and value.
template <class Key, class Value>
void restoreDictionary(istream &is, Dictionary<Key,Value> &D)
{	int len;
	is >> len;
	is.ignore(1,'\n');
 //	cout<<len<<endl;
	for(int i = 0; i<len; i++)
	{	Key key;
		Value value;
		is >> key;
		is.ignore(1,'\n');
	 //	cout<<key<<endl;
		is >> value;
		is.ignore(1,'\n');
	 //	cout<<value<<endl;
      D.atPut(key,value);
	}
}


#endif

