#ifndef _T_JQueue
#define _T_JQueue

/******************************************************************************
 JQueue.cc

								The Queue Class

	This class manages a queue.  The first template argument must be
	a derived class of JOrderedSet.  The second template argument is the
	data type of the stack.

	Refer to JArray.tmpl for warning associated with using JArray's.

	BASE CLASS = public JContainer

	Copyright © 1993-97 John Lindal. All rights reserved.

 ******************************************************************************/

#include <JQueue.h>
#include <jAssert.h>

/******************************************************************************
 Constructor

 ******************************************************************************/

template <class S, class T>
JQueue<S,T>::JQueue()
	:
	JContainer()
{
	itsElements = new S;
	assert( itsElements != NULL );

	InstallOrderedSet(itsElements);
}

/******************************************************************************
 Copy constructor

 ******************************************************************************/

template <class S, class T>
JQueue<S,T>::JQueue
	(
	const JQueue<S,T>& source
	)
	:
	JContainer(source)
{
	itsElements = new S(*(source.itsElements));
	assert( itsElements != NULL );

	InstallOrderedSet(itsElements);
}

/******************************************************************************
 Destructor

 ******************************************************************************/

template <class S, class T>
JQueue<S,T>::~JQueue()
{
	delete itsElements;
}

/******************************************************************************
 Assignment operator

 ******************************************************************************/

template <class S, class T>
const JQueue<S,T>&
JQueue<S,T>::operator=
	(
	const JQueue<S,T>& source
	)
{
	if (this == &source)
		{
		return *this;
		}

	JContainer::operator=(source);

	*itsElements = *(source.itsElements);
	return *this;
}

/******************************************************************************
 Append

	Add a new element to the end of the queue.

 ******************************************************************************/

template <class S, class T>
void
JQueue<S,T>::Append
	(
	const T& newElement
	)
{
	itsElements->AppendElement(newElement);
}

/******************************************************************************
 GetNext

	Remove the first element from the queue and return it.

 ******************************************************************************/

template <class S, class T>
T
JQueue<S,T>::GetNext()
{
	const T data = itsElements->GetElement(1);
	itsElements->RemoveElement(1);
	return data;
}

template <class S, class T>
JBoolean
JQueue<S,T>::GetNext
	(
	T* element
	)
{
	if (!IsEmpty())
		{
		*element = itsElements->GetElement(1);
		itsElements->RemoveElement(1);
		return kTrue;
		}
	else
		{
		return kFalse;
		}
}

/******************************************************************************
 PeekNext

	Return the first element in the queue without removing it.

 ******************************************************************************/

template <class S, class T>
const T
JQueue<S,T>::PeekNext()
{
	return itsElements->GetElement(1);
}

template <class S, class T>
JBoolean
JQueue<S,T>::PeekNext
	(
	T* element
	)
{
	if (!IsEmpty())
		{
		*element = itsElements->GetElement(1);
		return kTrue;
		}
	else
		{
		return kFalse;
		}
}

/******************************************************************************
 PeekNext

	Return the specified element in the queue without removing it.

 ******************************************************************************/

template <class S, class T>
const T
JQueue<S,T>::PeekNext
	(
	const JIndex index
	)
{
	return itsElements->GetElement(index);
}

template <class S, class T>
JBoolean
JQueue<S,T>::PeekNext
	(
	const JIndex	index,
	T*				element
	)
{
	if (IndexValid(index))
		{
		*element = itsElements->GetElement(index);
		return kTrue;
		}
	else
		{
		return kFalse;
		}
}

/******************************************************************************
 Flush

	Remove all the elements from the queue.

 ******************************************************************************/

template <class S, class T>
void
JQueue<S,T>::Flush()
{
	itsElements->RemoveAll();
}

/******************************************************************************
 Discard

	Remove the first few elements from the queue.

 ******************************************************************************/

template <class S, class T>
void
JQueue<S,T>::Discard
	(
	const JSize numToDiscard
	)
{
	JSize numDiscarded = 0;
	while (numDiscarded < numToDiscard && !itsElements->IsEmpty())
		{
		itsElements->RemoveElement(1);
		numDiscarded++;
		}
}

/******************************************************************************
 GetElements (protected)

 ******************************************************************************/

template <class S, class T>
S*
JQueue<S,T>::GetElements()
{
	return itsElements;
}

/******************************************************************************
 NewIterator

	This provides an iterator for looking at all the elements in the Queue.
	The caller must delete the iterator.

 ******************************************************************************/

template <class S, class T>
JOrderedSetIterator<T>*
JQueue<S,T>::NewIterator()
{
	return itsElements->NewIterator();
}

template <class S, class T>
JOrderedSetIterator<T>*
JQueue<S,T>::NewIterator()
	const
{
	return itsElements->NewIterator();
}

#endif

// Instantiate the template for the specified type.

#if defined JTemplateType && ! defined JOnlyWantTemplateDefinition
	#define JTemplateName JQueue
	#include <instantiate_template.h>
	#undef JTemplateName
#endif
