// -*- c++ -*-
//------------------------------------------------------------------------------
//                            PriorityQueue.h
//------------------------------------------------------------------------------
//  Copyright (c) 1999 by Vladislav Grinchenko
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//------------------------------------------------------------------------------
#ifndef PRIORITY_QUEUE_H
#define PRIORITY_QUEUE_H

#include <unistd.h>
#include <limits.h>

#include "assa/Assert.h"
#include "assa/PriorityQueue_Impl.h"
#include "assa/PriorityQueue_Heap.h"

namespace ASSA {

/** @file PriorityQueue.h

	Priority Queue class that allows removal of arbitrariy
	element from the queue. 
	This is Abstraction part of the Bridge pattern.
*/
 
template<class T, class Compare> class PriorityQueue_Impl;

template<class T, class Compare >
class PriorityQueue
{
public:
	PriorityQueue (size_t max_ = 20);
	PriorityQueue (size_t max_, const Compare&);

	virtual ~PriorityQueue ();

	virtual void     insert (const T&);
	virtual T        pop ();
	virtual const T& top () const;
	virtual bool     remove (T&);
	virtual size_t   size ();
	virtual T&       operator[] (int);

	virtual void setHeapImpl (size_t, const Compare&);

protected:
	const PriorityQueue_Impl<T, Compare>* getPriorityQueueImpl () const;
	Compare m_comp;

	PriorityQueue (const PriorityQueue&);
	PriorityQueue& operator= (const PriorityQueue&);

private:
	PriorityQueue_Impl< T, Compare >* m_impl;
};

//----------------------------------------------------------------------------
// Member functions
//----------------------------------------------------------------------------

template <class T, class Compare>
inline 
PriorityQueue<T, Compare>::
PriorityQueue (size_t maxsz_)
	: m_impl (0)
{
	// This is a perfect place for using Factory to decide which
	// implementation to use
	// const char self[]="PriorityQueue::PriorityQueue(maxsz)"; trace();

	setHeapImpl (maxsz_, m_comp);
}

template <class T, class Compare>
inline 
PriorityQueue<T, Compare>::
PriorityQueue (size_t maxsz_, const Compare& x_)
	: m_comp (x_), m_impl (0)
{
	// This is perfect place for using Factory to decide which
	// implementation to use
	setHeapImpl (maxsz_, m_comp);
}

template <class T, class Compare>
inline void
PriorityQueue<T, Compare>::
setHeapImpl (size_t maxsz_, const Compare& x_)
{
	// Maybe here you would want to copy contents of the old
	// implementation to the new one?
	//

	if (m_impl != 0)
		delete m_impl;

	m_impl = new PriorityQueue_Heap<T, Compare> (maxsz_, x_);
}

template <class T, class Compare>
inline
PriorityQueue<T, Compare>::
~PriorityQueue ()
{
	delete m_impl;
}

template <class T, class Compare> void
inline
PriorityQueue<T, Compare>::
insert (const T& el_)
{
	m_impl->insert (el_);
}

template <class T, class Compare> T
inline
PriorityQueue<T, Compare>::
pop ()
{
	return m_impl->pop ();
}

template <class T, class Compare> 
inline const T&
PriorityQueue<T, Compare>::
top () const
{
	return m_impl->top ();
}

template <class T, class Compare> 
inline bool
PriorityQueue<T, Compare>::
remove (T& t_)
{
	return m_impl->remove (t_);
}

template <class T, class Compare> 
inline size_t
PriorityQueue<T, Compare>::
size ()
{
	return m_impl->size ();
}

template <class T, class Compare> 
inline const PriorityQueue_Impl<T, Compare>*
PriorityQueue<T, Compare>::
getPriorityQueueImpl () const
{
	return (const PriorityQueue_Impl<T, Compare>*) m_impl;
}

template <class T, class Compare> 
inline T&
PriorityQueue<T, Compare>::
operator[] (int idx)
{
	return (*m_impl)[idx];
}

} // end namespace ASSA

#endif /* PRIORITY_QUEUE_H */  
