/////////////////////////////////////////////////////////////////////////////////////////
//
//	FILE:			Asura_Shape_System.h
//
//	AUTHOR:			Richard M. Smith (8 August 2002)
//
/////////////////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __ASURA_SHAPE_SYSTEM_H__
#define __ASURA_SHAPE_SYSTEM_H__

//////////////
// INCLUDES //
//////////////

#include "Core/Asura_HashTree.h"
#include "Debugging/Asura_Assert.h"
#include "Shapes/Asura_Shapes.h"


/////////////
// DEFINES //
/////////////
#ifndef ASURA_MAX_SHAPES
	#define	ASURA_MAX_SHAPES	( 300 )
#endif

/////////////
// CLASSES //
/////////////
class Asura_Bounding_Box;
class Asura_Stream;

/////////////////////////
// Asura_Shape_Handler //
/////////////////////////
class Asura_Shape_Handler
{
	friend class Asura_Shape_System;

public:
	// Public functions...
	Asura_Shape_Handler(void)	{}
//	~Asura_Shape_Handler();

	// Reset function...
			void			Reset			(void)												{ m_xShapeTree.Reset(); }

	// Loading function...
			void			LoadAllShapes	(void);

    // Retrieval function(s)...
			void			SetShapeData	(Asura_Hash_ID uHash, unsigned uFlags, Asura_Bounding_Box *pxBB);

			Asura_Shape*	NewShape		(Asura_Hash_ID uHash);
			Asura_Shape*	NewShape		(Asura_Hash_ID uHash, const Asura_Shape& xOther);
			Asura_Shape*	NewShape		(Asura_Hash_ID uHash, Asura_Chunk_Stream& xStream);
			bool			DeleteShape		(Asura_Shape* pxShape);

			Asura_Shape*	GetShape		(Asura_Hash_ID uHash)								{ return(m_xShapeTree.GetDataByHash(uHash)); }
			u_int			GetNumShapes	(void)												{ return(m_xShapeTree.GetNumberOfNodes()); }
#ifdef ASURA_TOOLS
			Asura_Shape*	GetShapeAtIndex	(unsigned int uIndex)								{ return(m_xShapeTree.GetDataByIndex(uIndex)); }
#endif //ASURA_TOOLS

private:
	// Private variables...
	Asura_TemplateHashTree<Asura_Shape>	m_xShapeTree;

	// Private functions...
	static	void			LoadShape		(Asura_Hash_ID uHash, Asura_Shape* pxShape);
};
// End class Asura_Shape_System


////////////////////////
// Asura_Shape_System //
////////////////////////
class Asura_Shape_System
{
	friend class Asura_Shape;
	friend class Asura_Shape_Handler;

public:
	// Initialise and shutdown...
	static	void					Initialise			(void);
	static	void					Shutdown			(void);
	static	void					Reset				(void);

	// Retrieval function(s)...
	static	void					SetShapeData		(Asura_Hash_ID uHash, unsigned uFlags, Asura_Bounding_Box *pxBB)	{ GetCurrentHandler().SetShapeData(uHash, uFlags, pxBB); }

	static	Asura_Shape*			NewShape			(Asura_Hash_ID uHash)												{ return(GetCurrentHandler().NewShape(uHash)); }
	static	Asura_Shape*			NewShape			(Asura_Hash_ID uHash, const Asura_Shape& xOther)					{ return(GetCurrentHandler().NewShape(uHash, xOther)); }
	static	Asura_Shape*			NewShape			(Asura_Hash_ID uHash, Asura_Chunk_Stream& xStream)					{ return(GetCurrentHandler().NewShape(uHash, xStream)); }
	static	bool					DeleteShape			(Asura_Shape* pxShape)												{ return(GetCurrentHandler().DeleteShape(pxShape)); }

	static	Asura_Shape*			GetShape			(Asura_Hash_ID uHash)												{ return(GetCurrentHandler().GetShape(uHash)); }
	static	u_int					GetNumShapes		(void)																{ return(GetCurrentHandler().GetNumShapes()); }
#ifdef ASURA_TOOLS
	static	Asura_Shape*			GetShapeAtIndex		(unsigned int uIndex)												{ return(GetCurrentHandler().GetShapeAtIndex(uIndex)); }
#endif //ASURA_TOOLS

	// Loading function...
	static	void					LoadAllShapes		(void)																{ GetCurrentHandler().LoadAllShapes(); }

#if defined(ASURA_USE_MULTIPLE_HANDLERS)
	// Handler functions...
	static	void					ReparentHandler(const Asura_Hash_ID uSourceHash, const Asura_Hash_ID uNewParentHash);
	static	void					ReparentHandler(Asura_Shape_Handler& xSourceHandler, const Asura_Hash_ID uNewParentHash);

	static	Asura_Shape_Handler*	CreateHandler		(const Asura_Hash_ID uHash, const Asura_Hash_ID uParentHandlerHash);
	static	bool					DestroyHandler		(const Asura_Hash_ID uHash);
	static	void					WriteHandlerReport	(u_int uHandler, Asura_Stream& xLog);

	static	void					CreateAndSetHandler	(const Asura_Hash_ID uHash, const Asura_Hash_ID uParentHandlerHash)	{ s_pxCurrentHandler = CreateHandler(uHash, uParentHandlerHash); }
	static	void					SetCurrentHandler	(Asura_Shape_Handler* pxHandler)									{ s_pxCurrentHandler = pxHandler; }
	static	void					SetCurrentHandler	(const Asura_Hash_ID uHash)											{ s_pxCurrentHandler = s_xHandlerTree.GetDataByHash(uHash); }
	static	Asura_Shape_Handler&	GetCurrentHandler	(void)																{ return(*s_pxCurrentHandler); }
	static	Asura_Shape_Handler*	GetHandler			(const Asura_Hash_ID uHash)											{ return(s_xHandlerTree.GetDataByHash(uHash)); }
#else
	// Handler functions...
	static	Asura_Shape_Handler&	GetCurrentHandler	(void)																{ return(s_xHandler); }
#endif

private:
#if defined(ASURA_USE_MULTIPLE_HANDLERS)
	// Private variables...
	static	Asura_Shape_Handler*						s_pxCurrentHandler;		// Currently active handler.
	static	Asura_TemplateHashTree<Asura_Shape_Handler>	s_xHandlerTree;			// Tree of all of the handlers available.
#else
	// Private variables...
	static	Asura_Shape_Handler							s_xHandler;				// Single static-instance of a zone.
#endif
};
// End class Asura_Shape_System


#endif //__ASURA_SHAPE_SYSTEM_H__

////////////////////////////////////// End of file //////////////////////////////////////
