//
// Asura_Handle.h
//
// Created by Kevin Lea - 12/06/2001 10:59:25
//
// Copyright (C) 2001 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __ASURA_HANDLE_H__
#define __ASURA_HANDLE_H__

#include "Debugging/Asura_Assert.h"

// (MH - 16.05.2007) moved these into Asura.h
//typedef int Asura_Handle;
//static const Asura_Handle ASURA_INVALID_HANDLE = -1;

class Asura_Handle_List
{
	public:
		Asura_Handle_List(int size)
		{
			List = new Asura_Handle[size];
			Position = 0;
			Size = size;

			for (int i=0; i<size; i++)
			{
				List[i] = i;
			}
		}
		virtual ~Asura_Handle_List()
		{
			delete [] List;
		}

        // (MH - 15.12.2002) trying to avoid fragmentation - Reset method avoid having to delete list
        void Reset()
        {
			Position = 0;

			for (int i=0; i<Size; i++)
			{
				List[i] = i;
			}
        }

		bool GetNewHandle(Asura_Handle& handle)
		{
			if (Position<Size)
			{
				handle = List[Position++];
				return true;
			}

			handle = ASURA_INVALID_HANDLE;

			return false;
		}

		virtual void ReleaseHandle(Asura_Handle handle)
		{
			if (Position>0 && handle!=ASURA_INVALID_HANDLE)
			{
				List[--Position] = handle;
			}
		}

		inline int GetNumberOfActiveHandles(void) const
		{
			return Position;
		}

		inline int GetTotalNumberOfHandles(void) const
		{
			return this->Size;
		}

        inline bool IsValidHandle( Asura_Handle iHandle ) const
        {
            return( 0 <= iHandle && iHandle < Size );
        }

	protected:
		Asura_Handle* List;
		int Size;
		int Position;
};

class Asura_Tracking_Handle_List;

class Asura_Tracking_Handle_List_Iterator
{
	public:

		Asura_Tracking_Handle_List_Iterator(void)
		{
			m_pxObjectToIterate = NULL;
			m_iIterationIndex = 0;
		}

		Asura_Tracking_Handle_List_Iterator(Asura_Tracking_Handle_List* pxObjectToIterate)
		{
			m_pxObjectToIterate = pxObjectToIterate;
			m_iIterationIndex = 0;
		}

		Asura_Tracking_Handle_List_Iterator(const Asura_Tracking_Handle_List_Iterator& xFrom)
		{
			m_pxObjectToIterate = xFrom.m_pxObjectToIterate;
			m_iIterationIndex   = xFrom.m_iIterationIndex;
		}
		inline void Begin(void);

		inline bool End(void) const
		{
			return (m_iIterationIndex < 0);
		}
		inline void Next(void)
		{
			m_iIterationIndex--;
		}

		inline Asura_Handle GetCurrentHandle(void) const;

	private:
		Asura_Tracking_Handle_List* m_pxObjectToIterate;
		int m_iIterationIndex;
};

class Asura_Tracking_Handle_List : public Asura_Handle_List
{
	friend class Asura_Tracking_Handle_List_Iterator;
	public:
		typedef class Asura_Tracking_Handle_List_Iterator Iterator;

		Asura_Tracking_Handle_List(int size) : Asura_Handle_List(size)
		{
		}

		virtual void ReleaseHandle(Asura_Handle handle)
		{
			for (int i=0; i<Position; i++)
			{
				if (List[i] == handle)
				{
					List[i] = List[--Position];
					List[Position] = handle;
					return;
				}
			}
			Asura_Assert(0,"Handle not found in active list");
		}

		Asura_Tracking_Handle_List_Iterator GetIterator(void)
		{
			return Asura_Tracking_Handle_List_Iterator(this);
		}

        void Traverse(void (*function)(Asura_Handle handle))
		{
			Iterator xTraversePosition = GetIterator();
			for ( xTraversePosition.Begin(); !xTraversePosition.End(); xTraversePosition.Next() )
			{
				function(xTraversePosition.GetCurrentHandle());
			}
		}

        inline bool IsActiveHandle( Asura_Handle iHandle ) const
        {
            for( int i = 0; i < Position; ++i )
            {
                if( List[i] == iHandle ) { return true; }
            }
            return false;
        }

	private:
};

void Asura_Tracking_Handle_List_Iterator::Begin(void)
{
	m_iIterationIndex = m_pxObjectToIterate->Position - 1;
}

Asura_Handle Asura_Tracking_Handle_List_Iterator::GetCurrentHandle(void) const
{
    Asura_Assert(m_iIterationIndex >= 0, "Bad iteration handle");
	return m_pxObjectToIterate->List[m_iIterationIndex];
}

#endif // __ASURA_HANDLE_H__
