//===========================================================================//
// File:	vchain.hh                                                           //
// Project: MUNGA           Brick: Connection Library                        //
// Contents: Interface specification of SortedChain class                         //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 12/02/94  ECH  Initial coding.                                            //
// 12/12/94  ECH  Changed release handling											  //
// 06/07/96  ECH  Implemented socket based remove functionality				  //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//

#pragma once

#include "Stuff.hpp"
#include "SortedSocket.hpp"
#include "MemoryBlock.hpp"

namespace Stuff {

	class SortedChain;
	class SortedChainIterator;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class _declspec(novtable) SortedChainLink:
		public Link
	{
		friend class SortedChain;
		friend class SortedChainIterator;

	public:
		void
			TestInstance();

	protected:
		~SortedChainLink();
		SortedChainLink(
			SortedChain *vchain,
			Plug *plug
		);

	private:
		void
			SetupSortedChainLinks(
				SortedChainLink *next,
				SortedChainLink *prev
			);

		SortedChainLink *m_next;
		SortedChainLink *m_prev;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChainLinkOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	template <class V> class SortedChainLinkOf:
		public SortedChainLink
	{
	public:
		SortedChainLinkOf(
			SortedChain *vchain,
			Plug *plug,
			const V &value
		):
			SortedChainLink(vchain, plug)
				{m_value = value;}

		void*
			operator new(size_t);
		void
			operator delete(void *where);

		V
			GetValue()
				{return m_value;}
		V*
			GetValuePointer()
				{return &m_value;}

	private:
		static MemoryBlock
			*s_allocatedMemory;
		static int
			s_allocationCount;

		V m_value;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChainLinkOf templates ~~~~~~~~~~~~~~~~~~~~~~~~

	template <class V> MemoryBlock*
		SortedChainLinkOf<V>::s_allocatedMemory = NULL;
	template <class V> int
		SortedChainLinkOf<V>::s_allocationCount = 0;

	template <class V> void*
		SortedChainLinkOf<V>::operator new(size_t)
	{
		Verify(s_allocationCount >= 0);
		if (s_allocationCount++ == 0)
		{
			s_allocatedMemory =
				new(g_Heap) MemoryBlock(
					sizeof(SortedChainLinkOf<V>),
					100,
					100,
					"Stuff::SortedChainLinkOf",
					Stuff::g_ConnectionEngineHeap
				);
			Check_Object(s_allocatedMemory);
		}
		Verify(s_allocationCount < INT_MAX);
		Check_Object(s_allocatedMemory);
		return s_allocatedMemory->New();
	}

	template <class V> void
		SortedChainLinkOf<V>::operator delete(void *where)
	{
		Check_Object(s_allocatedMemory);
		s_allocatedMemory->Delete(where);
		if (--s_allocationCount == 0)
		{
			Check_Object(s_allocatedMemory);
			delete s_allocatedMemory;
			s_allocatedMemory = NULL;
		}
		Verify(s_allocationCount >= 0);
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class _declspec(novtable) SortedChain:
		public SortedSocket
	{
		friend class SortedChainLink;
		friend class SortedChainIterator;

	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//

		//
		//--------------------------------------------------------------------
		// Constructor, Destructor and testing
		//--------------------------------------------------------------------
		//
		SortedChain(
			void *node,
			bool has_unique_entries
		);
		~SortedChain();

		void
			TestInstance();
		static bool
			TestClass();
		static bool
			ProfileClass();

		//
		//-----------------------------------------------------------------------
		// RemovePlug - Remove a plug from this socket, untyped access.
		//-----------------------------------------------------------------------
		//
		void
			DeletePlugs();

		//
		//-----------------------------------------------------------------------
		// IsPlugMember - Determine if the plug is a member of this socket.
		//-----------------------------------------------------------------------
		//
		void*
			GetNthItem(unsigned index);

		//
		//-----------------------------------------------------------------------
		// IsEmpty - Returns true if the socket contains no plugs.
		//-----------------------------------------------------------------------
		//
		unsigned
			GetSize();
		bool
			IsEmpty();

		void
			AddValuePlug(
				Plug *plug,
				const void *value
			);
		Plug*
			FindPlug(const void *value);

	protected:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		virtual SortedChainLink
			*MakeSortedChainLink(
				Plug *plug,
				const void *value
			)=0;
		virtual int
			CompareSortedChainLinks(
				SortedChainLink *link1,
				SortedChainLink *link2
			)=0;
		virtual int
			CompareValueToSortedChainLink(
				const void *value,
				SortedChainLink *link
			)=0;

		SortedChainLink*
			SearchForValue(const void *value);

		//
		//--------------------------------------------------------------------
		// Private data
		//--------------------------------------------------------------------
		//
		SortedChainLink
			*m_head,
			*m_tail;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChainOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	template <class T, class V> class SortedChainOf:
		public SortedChain
	{
	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		SortedChainOf(
			void *,
			bool has_unique_entries
		):
			SortedChain(NULL, has_unique_entries)
				{}

		void*
			operator new(size_t);
		void
			operator delete(void *where);

		//
		//--------------------------------------------------------------------
		// Socket methods (see Socket for full listing)
		//--------------------------------------------------------------------
		//
		T
			GetNth(unsigned index)
				{return (T)SortedChain::GetNthItem(index);}
		void
			Remove(T plug)
				{SortedChain::RemovePlug(Cast_Object(Plug*,plug));}
		void
			AddValue(
				T plug,
				const V &value
			)
				{SortedChain::AddValuePlug(Cast_Object(Plug*,plug), &value);}
		T
			Find(const V &value)
				{return (T)SortedChain::FindPlug(&value);}

	private:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		SortedChainLink
			*MakeSortedChainLink(
				Plug *plug,
				const void *value
			)
				{
					return
						new SortedChainLinkOf<V>(
							this,
							plug,
							*Cast_Pointer(const V*, value)
						);
				}
		int
			CompareSortedChainLinks(
				SortedChainLink *link1,
				SortedChainLink *link2
			);
		int
			CompareValueToSortedChainLink(
				const void *value,
				SortedChainLink *link
			);

		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private data
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		static MemoryBlock
			*s_allocatedMemory;
		static int
			s_allocationCount;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChainOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~

	template <class T, class V> MemoryBlock*
		SortedChainOf<T, V>::s_allocatedMemory = NULL;
	template <class T, class V> int
		SortedChainOf<T, V>::s_allocationCount = 0;

	template <class T, class V> void*
		SortedChainOf<T, V>::operator new(size_t)
	{
		Verify(s_allocationCount >= 0);
		if (s_allocationCount++ == 0)
		{
			s_allocatedMemory =
				new(g_Heap) MemoryBlock(
					sizeof(SortedChainOf<T, V>),
					100,
					100,
					"Stuff::SortedChainOf",
					Stuff::g_ConnectionEngineHeap
				);
			Check_Object(s_allocatedMemory);
		}
		Verify(s_allocationCount < INT_MAX);
		Check_Object(s_allocatedMemory);
		return s_allocatedMemory->New();
	}

	template <class T, class V> void
		SortedChainOf<T, V>::operator delete(void *where)
	{
		Check_Object(s_allocatedMemory);
		s_allocatedMemory->Delete(where);
		if (--s_allocationCount == 0)
		{
			Check_Object(s_allocatedMemory);
			delete s_allocatedMemory;
			s_allocatedMemory = NULL;
		}
		Verify(s_allocationCount >= 0);
	}

	template <class T, class V> int
		SortedChainOf<T, V>::CompareSortedChainLinks(
			SortedChainLink *node1,
			SortedChainLink *node2
		)
	{
		V *ptr1 = Cast_Object(SortedChainLinkOf<V>*, node1)->GetValuePointer();
		V *ptr2 = Cast_Object(SortedChainLinkOf<V>*, node2)->GetValuePointer();

		Check_Pointer(ptr1);
		Check_Pointer(ptr2);

		if (*ptr1 == *ptr2)
			return 0;
		else
			return ((*ptr1 > *ptr2) ? 1 : -1);
	}

	template <class T, class V> int
		SortedChainOf<T, V>::CompareValueToSortedChainLink(
			const void *value,
			SortedChainLink *node
		)
	{
		Check_Pointer(value);

		V *ptr = Cast_Object(SortedChainLinkOf<V>*, node)->GetValuePointer();
		Check_Pointer(ptr);

		if (*Cast_Pointer(const V*, value) == *ptr)
			return 0;
		else
			return (*Cast_Pointer(const V*, value) > *ptr) ? 1 : -1;
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class SortedChainIterator:
		public SortedIterator
	{
	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//

		//
		//--------------------------------------------------------------------
		// Constructors, Destructor and testing
		//--------------------------------------------------------------------
		//
		explicit SortedChainIterator(SortedChain *vchain);
		explicit SortedChainIterator(const SortedChainIterator *iterator);
		Iterator*
			MakeClone();
		~SortedChainIterator();
		void
			TestInstance() const;

		//
		//--------------------------------------------------------------------
		// Iterator methods (see Iterator for full listing)
		//--------------------------------------------------------------------
		//
		Iterator&
			First();
		Iterator&
			Last();
		Iterator&
			Next();
		Iterator&
			Previous();
		void*
			ReadAndNextItem();
		void*
			ReadAndPreviousItem();
		void*
			GetCurrentItem();
		void*
			GetNthItem(unsigned index);

		void
			Remove();

		Plug*
			FindPlug(const void *value);
		void*
			GetPlugValue();

	protected:
		//
		//--------------------------------------------------------------------
		// Protected data
		//--------------------------------------------------------------------
		//
		SortedChainLink
			*m_currentLink;

		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		void
			ReceiveMemo(
				IteratorMemo memo,
				void *content
			);
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~ SortedChainIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	template <class T, class V> class SortedChainIteratorOf:
		public SortedChainIterator
	{
	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//

		//
		//--------------------------------------------------------------------
		// Constructors and Destructor
		//--------------------------------------------------------------------
		//
		explicit SortedChainIteratorOf(SortedChainOf<T, V> *vchain):
			SortedChainIterator(vchain)
				{}
		explicit SortedChainIteratorOf(const SortedChainIteratorOf<T, V> &iterator):
			SortedChainIterator(&iterator)
				{}
		Iterator*
			MakeClone()
				{return new SortedChainIteratorOf<T, V>(*this);}

		//
		//--------------------------------------------------------------------
		// Iterator methods (see Iterator for full listing)
		//--------------------------------------------------------------------
		//
		T
			ReadAndNext()
				{return (T)SortedChainIterator::ReadAndNextItem();}
		T
			ReadAndPrevious()
				{return (T)SortedChainIterator::ReadAndPreviousItem();}
		T
			GetCurrent()
				{return (T)SortedChainIterator::GetCurrentItem();}
		T
			GetNth(unsigned index)
				{return (T)SortedChainIterator::GetNthItem(index);}
		T
			Find(const V &value)
				{return (T)SortedChainIterator::FindPlug(&value);}
		V
			GetValue()
				{return Cast_Object(SortedChainLinkOf<V>*, m_currentLink)->GetValue();}

		operator T()
			{return SortedChainIterator::GetCurrent();}
	};

}
