///////////////////////////////////////////////////////////////////////////////
/// @file deApi.hpp
///
/// @brief DestinyEdit API
///
/// @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
///
///////////////////////////////////////////////////////////////////////////////

#define USING_DESTINY3D
#define DESTINY3D_STATIC_LINK
#define DEAPI_VERSION 50

#include "deGlobalTypes.hpp"
#include "deFileSystem.hpp"
#include "deArray.hpp"
#include "deString.hpp"
#include "deList.hpp"
#include "deRender.hpp"
#include "deCamera.hpp"
#include "deScene.hpp"
#include "deDriver.hpp"
#include "de2D.hpp"
#include "deBitmap.hpp"
#include "deBrush.hpp"


#ifdef DEAPI_EXPORT
#define DEAPI DEDLL_EXPORT
#else
#define DEAPI DEDLL_IMPORT
#pragma comment(lib,"deApi")
#endif

#ifdef WIN32
#include "windows.h"
#endif

//
// Forward Defines
//
class deApi;
//
// Api Types
class deApiTypes;
//
// Api Object Handles
class deApiHandle;
//
// Api Objects
class deApiObject;
class deApiNode;
class deApiNodeTree;
class deApiAttribute;
class deApiAttribute_Float;
class deApiAttributeCollection;
class deApiStaticBrush;
class deApiOutputWindow;
class deApiRender;
class deApiCamera;
class deApiViewport;
class deApiViewportLayout;
//
// Function Sets
class deApiFn_Attribute;
class deApiFn_OutputWindow;
class deApiFn_NodeTree;
class deApiFn_Render;
class deApiFn_Camera;
class deApiFn_Viewport;
class deApiFn_ViewportLayout;

//
// deApiType
//
// This class provides dynamic runtime type information services for the api
#define DECLARE_RTI \
	public:\
		static deApiType Type;

#define DEFINE_RTI(name,parent)\
	deApiType name::Type(#name, &parent::Type);
#define DECLARE_RTI_BASE(name)\
	deApiType name::Type(#name, NULL);

class DEAPI deApiType
{
	public:
		deApiType();
		deApiType(const deString& sName, deApiType* pParent);
		virtual ~deApiType();
		deString& GetName();
		deString& GetParentName();
		deString& GetBaseName();
		deApiType* GetParent();
		deApiType* GetBase();
		bool IsA(const deApiType* pType);
		bool IsA(const deString& sType);
		// todo
		// implement downcasting from base to derived
		void* SafeCast(const deApiType* pCastTo);
		void* SafeCast(const deString& sType);
	private:
		deString	m_sName;
		deApiType*	m_pParent;
};

//
// deApiTypes
//
// This class simply defines some enumerated types used elsewhere
class DEAPI deApiTypes
{
	public:
		enum StatusCode
		{
			sError = -1000,
			sInvalidFunctionSet,
			sInvalidObjectType,
			sNullObject,
			sInvalidAttributeType,
			sOk = 0,
			sOutOfRange = 65535
		};
};

//
// Api Object Handles
//
// deApiHandle
//
// Encapsulates an api object handle, shielding the actual object behind the 
// handle for safety and security
class DEAPI deApiHandle
{
	friend class deApiNodeTree;

	public:
		//
		// Used to query the handle to see if it is useable with a specified function set
//		bool CanUseApiFnSet(deApiTypes::FunctionSet fnType);
		bool IsA(const deApiType* pType);
		bool IsA(const deString& sType);
		//
		// Does the handle reference a null or invalid api object?
		bool IsNull();
		//
		// Return the underlying object's runtime ID
		unsigned long GetRuntimeID();
		//
		// Destroy the underlying api object referenced by this handle.
		// The object will not be physically destroyed until this and
		// all other outstanding handles are released.  This only flags
		// it for destruction.
		bool Destroy();
		//
		// Overloaded assignment operator
		deApiHandle& operator=(deApiHandle& rhs);
		//
		// Overloaded copy constructor
		deApiHandle(const deApiHandle& rhs);
		//
		// Default constructor
		deApiHandle();
		//
		// Default destructor
		~deApiHandle();
	private:
		// 
		// Used by deApiObjectNodeTree to link the handle to its underlying api object
		void SetRuntimeID(unsigned long runtimeID);
		//
		// Helper function to de-reference underlying object for internal use
		deApiObject* Dereference();
	private:
		//
		// Underlying object's runtime ID. The handle itself does not have a runtime ID
		unsigned long	runtimeID;
		//
		// Is the underlying object invalid?
		bool			bNull;
};


#ifdef DEAPI_PRIVATE
	#include "../../deApi/deApi_Private.hpp"
#endif

//
// Function Sets
//
//
// deApiFn_Attribute
//
// Function set for working with attribute objects.  Creation and Manipulation.
class DEAPI deApiFn_Attribute
{
	public:
		enum DataType
		{
			Invalid = 0,
			Float,
			Int,
			Vector,
			Bool,
			Color_RGB,
			Color_Alpha,
			Color_ARGB,
			UV,
			UVW,
			Transform,
			OutOfRange = 65535
		};

		deApiFn_Attribute();
		~deApiFn_Attribute();

		//
		// Create a new attribute object with the specified parameters
		deApiHandle Create(DataType AttributeType, const deString& sName, const deString& sDescription);
		//
		// Add this attribute to the specified collection
		bool AddToCollection(deApiObject* pCollection);

	// TODO:
	// Hook this into the handle stuff, and decide whether to split
	// the collections off into a seperate function set or not.  Also make
	// the attribute member object into a generic base class if possible
	private:
		deApiAttribute*				m_pAttribute;
		deApiAttributeCollection*	m_pAttributeCollection;
		DataType					m_type;
};
//
// deApiFn_OutputWindow
//
// Provides functions for manipulating a text output/log window for the editor/api.
class DEAPI deApiFn_OutputWindow 
{
	public:
		//
		// default constructor
		deApiFn_OutputWindow();
		//
		// default destructor
		~deApiFn_OutputWindow();
		//
		// Create a new output window
		deApiHandle Create(int x, int y, int width, int height, const deString& title, bool bSizeable=true, bool bCaption=true);
		//
		// Bind function set to an existing handle
		deApiTypes::StatusCode BindHandle(deApiHandle handle);
		//
		// Add text to the output window. This function will add a complete
		// line of text to the output window, and add a carriage return/line feed
		// to the end.
		void AddLogText(const deString& sText);
		//
		// Show or Hide the output window
		void Hide(bool bHide);
		//
		// Save the contents of the window to a text file
		void WriteToFile(const deString& sFileName);
	private:
		deApiOutputWindow*	pOutputWindow;
};
//
// deApiFn_NodeTree
//
// Provides functions for manipulating the underlying node tree itself.  The node tree is
// the lower level tree orginazation where every persistent object is stored.  This 
// tree is also a linkage of operations.  Nodes can be connected together to form a chain
// of operations, with the output of one feeding into the input of the next.
class DEAPI deApiFn_NodeTree
{
	public:
		deApiHandle GetNode(unsigned long iRuntimeID);
      void GetNodes(deTArray<unsigned long>& aReturn, deString& TypeFilter = deString(""), int iMaxCount = -1);
};
//
// deApiFn_Render
//
// Encapsulates both the rendering and display subsystems of Destiny3D.
// Most of this is automated for simple use, though more advanced hooks
// will probably be provided later on.
class DEAPI deApiFn_Render
{
	public:
		void Init(deString& sDriverName);
		void Update(float fTime);
};
//
// deApiFn_Camera
//
// Creation and manipulation of cameras
class DEAPI deApiFn_Camera
{
	public:
		deApiHandle Create();
		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);
   private:
      deApiCamera       *m_pCamera;
};
//
// deApiFn_Viewport
//
// Creation and manipulation of viewports
class DEAPI deApiFn_Viewport
{
	public:
		void Hide(bool bHide);
		void Freeze(bool bFreeze);
		deApiTypes::StatusCode SetCamera(deApiHandle hCamera);
		void SetBGColor(deARGB color);
      void Maximize(bool bMaximized);
      void SetName(const deString& sName);
      deString& GetName();
};
//
// deApiFn_ViewportLayout
//
// A "Viewport Layout" defines the layout of the currently displayed viewports.
// The layout defines how many viewports are visible, the relative width and height of each viewport,
// the camera attached to each, as well as the name of each.
// Layouts can be saved, loaded, and edited in realtime by the user.  The viewport layout only defines
// the layout at the time the layout is applied.  Any characteristic of it can subsequently be changed
// by the user, and thus its properties should not be assumed.
//
// Note: When creating a layout, it is important to make sure you do not leave any window space uncovered
// by viewports.  In otherwords, the combined width and height of all viewports must be EQUAL to 100%.
// The results are undefined (read unpredictable), if the combined values are less than or greater than 100%.
class DEAPI deApiFn_ViewportLayout
{
   public:
      deApiHandle Create();
      void SetName(const deString& sName);
      deString& GetName();
      void WriteToFile(const deString& sFileName);
      void LoadFromFile(const deString& sFileName);
      void SetViewportCount(int iViewports);
      int GetViewportCount();
      void SetViewportRect(int iViewport, deFloatRect fRect);
      deFloatRect GetViewportRect(int iViewport);
      void SetViewportName(const deString& sName);
      deString& GetViewportName();
      void SetViewportCamera(int iViewport, deApiHandle hCamera);
      deApiHandle GetViewportCamera(int iViewport);
   private:
      deTArray<deFloatRect>      m_arrayViewportRects;
      deTArray<deString>         m_sViewportNames;
};


//
// Helper Macros
#define DEAPI_FAILED(status)(status < 0)
#define DEAPI_SUCCEEDED(status)(status >= 0)
#define DEAPI_PASSED(status)(status >= 0)

//
// Stand-Alone API Init
//
// This is used only when developing a stand-alone application that uses the API, but is
// not a plug-in to the editor.  When developing a standard plugin, this must not be used
extern "C" DEAPI bool deApi_InitStandAlone(HWND hParentWindow);
