///////////////////////////////////////////////////////////////////////////////
/// @file deApi_Private.hpp
///
/// @brief DestinyEdit API, private header
///
/// @author jwvanderbeck
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Mar 2003
/// @author jwvanderbeck
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////

//
// Utility Macros
//
#ifdef _DEBUG
#define DBGOUT(text)\
	TheApi.DebugOut(text);
#else
#define DBGOUT(text)
#endif
//
// deApi
//
// Essentially, the main API manager.
// deApi is a Singleton
// ************************************************************************************
// IMPORTANT: Plugins should never, ever, call this class directly, and it should never
// be instantiated by anyone outside of the system itself!
// ************************************************************************************
//
// ************************************************************************
// IMPORTANT: This singleton class will be moved BEHIND the scenes, and not
// exposed to the public api (not even the definition).
// It will be used internally only.
// ************************************************************************
class deApi
{
	friend class deApiHandle;

	public:

		//
		// This function really inits the whole ball of wax and is very important!
		bool InitApi(HWND hWindow);
		//
		// Determine the next available runtime ID
		unsigned long GetNextRuntimeID();
		//
		// Get a handle to the Node Tree.  Never call directly.  Use deApiFn_NodeTree
		deApiHandle GetNodeTree();
		//
		// These methods are used by function sets in order to create
		// the objects they will work on.
		deApiHandle CreateObject(deApiObject* pObject);
		bool DestroyObject(unsigned long runtimeID);
		//
		// Access to the underlying window handle
		HWND GetWindowHandle() { return m_hWindow; }
		//
		// Exchange a handle for an object pointer
		deApiObject* GetObjectFromHandle(deApiHandle handle);
		//
		// Output some text to the API's default output window
		// This is only active in debug mode
		void DebugOut(const deString& sText);
//	private:
		//
		// These are marked private for now.  There should be no reason
		// to make them available to derived classes.
		//
		//
		// The ID stuff needs to be updated to allow reuse of destroyed IDs
		//
		unsigned long			runtimeID;	// Next runtime ID to be assigned
		deApiNodeTree*			m_pNodeTree; // The one and only node tree class
		deApiRender*			m_pRender;
		HWND					m_hWindow;
		unsigned long			m_iOutputWindow;
};
//
// Access to deApi singleton - VERY IMPORTANT!!!
//
#define TheApi deApi_GetManager()

//
// Api Objects
//
//
// deApiObject
//
// Essentially, the root of the object side of the house.  This class in its base form
// really doesn't do much at all, but it is the base from which all api objects are built 
// on.  
// This class should never be instantiated by anyone.
class deApiObject
{
	public:
		deApiObject();
		virtual ~deApiObject();

		DECLARE_RTI;
/*		virtual deApiTypes::FunctionSet GetApiFnType();
		virtual deApiTypes::ObjectType GetApiObjectType();
		virtual bool CanUseApiFnSet(deApiTypes::FunctionSet fnType);*/

		virtual bool IsNull();

		virtual unsigned long GetRuntimeID();
		virtual unsigned long GetGlobalIDPrefix();
		virtual unsigned char GetGlobalID();
		// debug routines - will probably remove these once everything is working smoothly
		virtual void DumpObject();
		virtual int GetReferenceCount();
		virtual void RemoveReference();
		virtual void AddReference();
	
	protected:
		bool					bNull;
		int						iReferenceCount;
};
DECLARE_RTI_BASE(deApiObject);
//
// deApiNodeTree
//
// Provides a means for locating nodes within the tree, walking the tree,
// and other misc access routines against the tree itself.  Does not
// deal with nor encompass any specific nodes.
class deApiNodeTree : public deApiObject
{
	//
	// deApi is a friend here to allow it to access the methods to create
	// nodes which are hidden from the public for safety
	friend class deApi;
	//
	// deApiHandle is a friend to allow direct lookups of the api objects
	// instead of handles.  Only deApiHandle should ever be doing these
	// direct lookups
	friend class deApiHandle;
	friend class deApiFn;
	//
	public:
		//
		// Retrieves a handle to the object with the specified runtime ID
		deApiHandle GetNode(unsigned long runtimeID);
      //
      // Retrieves an array of runtime ids with configurable filters
      void GetNodes(deTArray<unsigned long>& aReturn, deString& TypeFilter = deString(""), int iMaxCount = -1);
		//
		// Default Constructor
		deApiNodeTree();
		//
		// Default Destructor
		~deApiNodeTree();
		//
		DECLARE_RTI;
		// Function Set and Object Type defs
//		FN_DEF(fnNodeTree)
//		OT_DEF(otNodeTree)
	private:
		//
		// Inserts the specified object pointer into the tree's array.
		// The new runtime ID for the node will be returned, with 0 indicating a failure
		// If the array is not large enough, it will automaticly
		// be resized.
		unsigned long AddNode(deApiObject* pNewObject);
		//
		// Removes the specified node and destroys the underlying object
		bool DestroyNode(unsigned long runtimeID);
		//
		// Returns the actual underlying api object for a given runtime ID
		// This is used by deApiHandle and deApi, and no one else should ever be doing
		// this de-reference.
		deApiObject* GetApiObject(unsigned long runtimeID);
	//
	private:
		deTArray<deApiObject*>	m_tarrayNodes;
		deTArray<unsigned long>	m_runtimeIDs;
//		deTList<unsigned long>	m_runtimeIDs;
};
DEFINE_RTI(deApiNodeTree,deApiObject);
//
// deApiNode
//
// Root class for any api object which is a node (Which is most, but not all api objects)
// This root class provides the basic common functions all nodes need.
class deApiNode : public deApiObject
{
	public:
		deApiNode() {};
		~deApiNode() {};
		DECLARE_RTI;
};
DEFINE_RTI(deApiNode,deApiObject);
//
// deApiStaticBrush
//
// Represents a StaticBrushNode, which is a specific type of node that
// generates a Destiny3D StaticBrush.
class deApiStaticBrush : public deApiNode
{
	DECLARE_RTI;
};
DEFINE_RTI(deApiStaticBrush,deApiNode);
//
// deApiAttribute
//
// Represents a single specific attribute, which could be either an input or output
// attribute on a node.  This is the base attribute class and should not be used
// directly.  Instead, a derived class covering the specific attribute type should
// be used.
class deApiAttribute: public deApiObject
{
	public:
		enum Type
		{
			Invalid = 0,
			Float,
			Int,
			Vector,
			Bool,
			Color_RGB,
			Color_Alpha,
			Color_RGBA,
			UV,
			UVW,
			Transform,
			OutOfRange = 65535
		};
		deApiAttribute();
		~deApiAttribute();
		Type GetAttributeType();
		unsigned long GetRuntimeID();
		//
		// Function Set and Object Type defs
//		DECLARE_RTI;
//		FN_DEF(fnAttribute)
//		OT_DEF(otAttribute)
	protected:
		unsigned long	runtimeID;
};
//DEFINE_RTI(deApiAttribute,deApiObject);
//
// deApiAttribute_Float
//
// A float attribute.  See base class deApiAttribute for more information on attributes.
class deApiAttribute_Float : public deApiAttribute
{
	public:
		deApiAttribute_Float();
		~deApiAttribute_Float();
		Type GetAttributeType();
		void DumpObject();
//		DECLARE_RTI;
	private:
		float	data;
};
//DEFINE_RTI(deApiAttribute_Float,deApiAttribute);
//
// deApiAttributeCollection
//
// Collection of attributes which is then applied as either the "inputs" or "outputs" for a node.
// A node can only have a single collection for each.
class deApiAttributeCollection : public deApiObject
{
	public:
		deApiAttributeCollection();
		~deApiAttributeCollection();

		DECLARE_RTI;
/*		deApiTypes::FunctionSet GetApiFnType();
		deApiTypes::ObjectType GetApiObjectType();
		bool CanUseApiFnSet(deApiTypes::FunctionSet fnType);*/

		bool IsNull();

		unsigned short GetAttributeCount();
		deApiObject* GetAttribute(unsigned long runtimeID);
		void DumpObject();

		bool AddAttribute(deApiObject* pAttribute);
	private:
		// Array of bound individual attributes in this collection
		deTArray<unsigned long>		m_tarrayAttributes;
};
DEFINE_RTI(deApiAttributeCollection,deApiObject);
//
// deApiOutputWindow
//
// Instance of a standard output/log window
class deApiOutputWindow : public deApiObject
{
	public:
		//
		// default constructor
		deApiOutputWindow();
		//
		// default destructor
		~deApiOutputWindow();
		//
		// Create the output window
		deApiTypes::StatusCode CreateOutputWindow(int x, int y, int width, int height, const char* title, bool bSizeable = true, bool bCaption = true);
		//
		// Destroy the output window
		void DestroyOutputWindow() { if(m_hWindow) DestroyWindow(m_hWindow); }
		//
		// Retrieve the window handle
		HWND GetWindowHandle() { return m_hWindow; }
		//
		// Add text to the log
		void AddLogText(const deString& text);
		//
		// Hide of Show the window
		void Hide(bool bHide);
		//
		// Get the contents of the window
		deString GetLogText();
		//
		// Function Set and Object Type defs
		DECLARE_RTI;
//		FN_DEF(fnOutputWindow)
//		OT_DEF(otOutputWindow)
	private:
		HWND		m_hWindow;
		deString	m_sText;
};
DEFINE_RTI(deApiOutputWindow,deApiObject);
//
// deApiRender
//
// Encapsulates the render and driver subsystems
// Most of this is used internally.  The API will automaticlly handle
// setup and rendering.  The controlling application just needs to call an
// update once per frame.
class deApiRender : public deApiObject
{
	DECLARE_RTI;
	public:
		bool Init(deString& sDriverName);
		void BeginFrame();
		void EndFrame();
		void Render();
		void SetState();
	private:
		IdeRender*		m_pRender;
		IdeDriver*		m_pDriver;
};
DEFINE_RTI(deApiRender, deApiObject);
//
// deApiCamera
//
// Camera controls
class deApiCamera : public deApiObject
{
	DECLARE_RTI;
   public:
      deApiCamera();
      virtual ~deApiCamera();

		void SetFOV(deDouble dDegrees);
		void SetOrthoWidth(deDouble dWidth);
		void EnableOrtho(bool bEnable);
		deTransform GetTransform();
		void SetTransform(deTransform transform);
		void SetName(const deString& sName);
		deString& GetName();
		deDouble GetFOV();
		deDouble GetOrthoWidth();
		bool IsOrtho();
		deDouble GetNearClip();
		deDouble GetFarClip();
		void SetClip(deDouble dNear, deDouble dFar);
      IdeCamera* GetDestinyCamera();
   private:
      IdeCamera*     m_pCamera;
      deString       m_sName;
      deDouble       m_dFOV;
      deDouble       m_dOrthoWidth;
      bool           m_bIsOrtho;
      deDouble       m_dNearClip;
      deDouble       m_dFarClip;
      deTransform    m_Transform;
};
DEFINE_RTI(deApiCamera, deApiObject);
