#ifndef _LIB_DESCRIPTION_H_
#define _LIB_DESCRIPTION_H_

#include "c4d_library.h"
#include "c4d_basecontainer.h"


#define DESCID_ROOT						DescID(DescLevel(1000491,0,0))
#define DESCID_DYNAMICSUB			DescLevel(700,DTYPE_SUBCONTAINER,0)
#define DESCID_DYNAMICGROUP		DescLevel(700,DTYPE_GROUP,0)


class BaseList2D;
class SubDialog;
class BCResourceObj;
class DescEntry;

struct RESOURCEDATATYPEPLUGIN;

// flags for GetDescription
#define DESCFLAGS_DESC_RESOLVEMULTIPLEDATA	(1<<0)
#define DESCFLAGS_DESC_LOADED								(1<<1)
#define DESCFLAGS_DESC_RECURSIONLOCK				(1<<2)

// flags for GetDParameter/SetDParameter
#define DESCFLAGS_PARAM_GET									(1<<1)
#define DESCFLAGS_PARAM_SET									(1<<1)
#define DESCFLAGS_USERINTERACTION						(1<<2)
#define DESCFLAGS_DONTCHECKMINMAX						(1<<3)

// defines for description
enum
{
	DTYPE_NONE					= 0,

	DTYPE_CHILDS				= 0,
	DTYPE_GROUP					= 1,
	DTYPE_COLOR					= 3,
	DTYPE_SUBCONTAINER  = 5,	// subcontainer data
	DTYPE_MULTIPLEDATA  = 6,	// multiple data entry
	DTYPE_TEXTURE				= 7,	// String: Texturename
	DTYPE_BUTTON				= 8,
	DTYPE_DYNAMIC				= 10, // for graphview "DYNAMIC"
	DTYPE_SEPARATOR			= 11, //
	DTYPE_STATICTEXT		= 12, //

	DTYPE_LONG					= 15,
	DTYPE_REAL					= 19,
	DTYPE_TIME					= 22,
	DTYPE_VECTOR				= 23,
	DTYPE_MATRIX				= 25,
	DTYPE_STRING				= 130,
	DTYPE_FILENAME			= 131, // DA_FILENAME
	DTYPE_BASELISTLINK	= 133,
	DTYPE_BOOL					= 400006001,//ID_GV_DATA_TYPE_BOOL
	DTYPE_NORMAL				= 400006005,//ID_GV_DATA_TYPE_NORMAL

	//--------------------
	DESC_NAME						= 1,					// name for parameter standalone use
	DESC_SHORT_NAME			= 2,					// short name (only for attribute dialog)

	DESC_VERSION				= 3,					// LONG: bitmask of the following values DESC_VERSION_xxx
		DESC_VERSION_DEMO		= (1<<0),
		DESC_VERSION_XL			= (1<<1),
		DESC_VERSION_ALL		= DESC_VERSION_DEMO|DESC_VERSION_XL,
	DESC_CHILDS					= 4,					// BaseContainer
	DESC_MIN						= 5,					// LONG/Real/Vector minimum INcluded
	DESC_MAX						= 6,					// LONG/Real/Vector maximum INcluded
	DESC_MINEX					= 7,					// Bool: TRUE == minimum EXcluded
	DESC_MAXEX					= 8,					// Bool: TRUE == maximum EXcluded
	DESC_STEP						= 9,					// LONG/Real/Vector
	DESC_ANIMATE				= 10,					// LONG
		DESC_ANIMATE_OFF		= 0,
		DESC_ANIMATE_ON			= 1,
		DESC_ANIMATE_MIX		= 2,
	DESC_ASKOBJECT			= 11,					// Bool: TRUE - ask object for this parameter, FALSE - lookinside container
	DESC_UNIT						= 12,					// LONG: one of the following values DESC_UNIT_xxx for DTYPE_REAL/DTYPE_VECTOR
		DESC_UNIT_REAL			= 'frea',		//FORMAT_REAL,
		DESC_UNIT_LONG			= 'flng',		//FORMAT_LONG,
		DESC_UNIT_PERCENT		= 'fpct',		//FORMAT_PERCENT,
		DESC_UNIT_DEGREE		= 'fdgr',		//FORMAT_DEGREE,
		DESC_UNIT_METER			= 'fmet',		//FORMAT_METER,
		DESC_UNIT_TIME			= 'ffrm',		//FORMAT_FRAMES,
//DESC_PARENTGROUP		= 13,					// LONG: parent id
	DESC_CYCLE					= 14,					// Container: members of cycle
	DESC_HIDE						= 15,					// Bool: indicatesa wheter the propertie is hidden or not
	DESC_DEFAULT				= 16,					// default value for LONG/Real/Vector:
	DESC_ACCEPT					= 17,					// ACCEPT: for InstanceOf-Check()
	DESC_SEPARATORLINE	= 18,
	DESC_REFUSE					= 19,					// REFUSE: for InstanceOf-Check()
	DESC_PARENTID				= 20,					// for indent and anim track can append the parent-name
	DESC_CUSTOMGUI			= 21,					// customgui for this property
		#define CUSTOMGUI_REAL						DTYPE_REAL
		#define CUSTOMGUI_REALSLIDER			1000489
		#define CUSTOMGUI_REALSLIDERONLY	200000006
		#define CUSTOMGUI_VECTOR					DTYPE_VECTOR
		#define CUSTOMGUI_STRING					DTYPE_STRING
		#define CUSTOMGUI_STRINGMULTI			200000007
		#define CUSTOMGUI_STATICTEXT			DTYPE_STATICTEXT
		#define CUSTOMGUI_LONG						DTYPE_LONG
		#define CUSTOMGUI_LONGSLIDER			1000490
		#define CUSTOMGUI_BOOL						DTYPE_BOOL
		#define CUSTOMGUI_TIME						DTYPE_TIME
		#define CUSTOMGUI_COLOR						1000492
		#define CUSTOMGUI_MATRIX					DTYPE_MATRIX
		#define CUSTOMGUI_BUTTON					DTYPE_BUTTON
		#define CUSTOMGUI_SEPARATOR				DTYPE_SEPARATOR
		#define CUSTOMGUI_SUBDESCRIPTION	0


	DESC_COLUMNS				= 22,					// DTYPE_GROUP: number of columns
	DESC_LAYOUTGROUP		= 23,					// Bool: only for layout in columns, in layoutgroups are only groups allowed!
	DESC_REMOVEABLE			= 24,					// Bool: TRUE allows to remove this entry
	DESC_GUIOPEN				= 25,					// Bool: default open
	DESC_EDITABLE				= 26,					// Bool: TRUE allows to edit this entry
	DESC_MINSLIDER			= 27,					// LONG/Real/Vector minimum INcluded
	DESC_MAXSLIDER			= 28,					// LONG/Real/Vector maximum INcluded
	DESC_GROUPSCALEV		= 29,					// Bool: allow to scale group height

	// port extension for graphview
	DESC_INPORT					= 50,
	DESC_OUTPORT				= 51,
	DESC_STATICPORT			= 52,
	DESC_NEEDCONNECTION	= 53,
	DESC_MULTIPLE				= 54,
	DESC_PORTONLY				= 55,
	DESC_CREATEPORT			= 56,
	DESC_PORTSMIN				= 57,
	DESC_PORTSMAX				= 58,
	DESC_NOTMOVABLE			= 59,
	DESC_EDITPORT				= 60,
	DESC_ITERATOR				= 61,

	DESC_
};

#ifndef __API_INTERN__

#include "c4d_customdatatype.h"

#define CUSTOMDATATYPE_DESCID		1000486

enum
{
	VECTOR_X		= 1000,
	VECTOR_Y		= 1001,
	VECTOR_Z		= 1002
};

struct DescLevel
{
	LONG	id;
	LONG	dtype;
	LONG	creator;

	DescLevel(LONG t_id) : id(t_id), dtype(0), creator(0) { }
	DescLevel(LONG t_id, LONG t_datatype, LONG t_creator) : id(t_id), dtype(t_datatype), creator(t_creator) { }

	Bool operator == (const DescLevel &d) const;
	Bool operator != (const DescLevel &d) const;
};

class DescID : public iCustomDataType<DescID>
{
		LONG temp1;
		LONG *temp2;

	public:
		DescID();
		DescID(const DescID &src);
		DescID(const DescLevel &id1);
		DescID(const DescLevel &id1,const DescLevel &id2);
		DescID(const DescLevel &id1,const DescLevel &id2,const DescLevel &id3);
		~DescID();

		void SetId(const DescLevel &subid);
		void PushId(const DescLevel &subid);
		void PopId();
		const DescLevel &operator[] (LONG pos) const;
		const DescID& operator = (const DescID &id);
		Bool operator == (const DescID &d) const;
		Bool operator != (const DescID &d) const;
		const DescID operator <<(LONG shift) const;

		LONG GetDepth() const;
		Bool IsPartOf(const DescID &cmp,LONG *pos) const;
};

class Description
{
	private:
		Description();

	public:
		static Description *Alloc();
		static void Free(Description *&description);

		Bool LoadDescription(const BCResourceObj *bc,Bool copy);
		Bool LoadDescription(LONG id);
		Bool LoadDescription(const String &id);
		Bool SortGroups();

		const BCResourceObj* GetDescription();														// returns the complete description
		const BaseContainer* GetParameter(const DescID &id,BaseContainer &temp,AtomArray *ar);							// returns the specified property
		BaseContainer* GetParameterI(const DescID &id,AtomArray *ar);										// returns the specified property
		Bool SetParameter(const DescID &id,const BaseContainer &param,const DescID &groupid);		// returns the specified property

		void *BrowseInit();																								// browse property start, dont forget to call xxxFree
		Bool GetNext(void *handle,const BaseContainer **bc,DescID &id,DescID &groupid);					// returns all properties sequently
		void BrowseFree(void *&handle);																		// browse property free

		DescEntry *GetFirst(const AtomArray &op);
		DescEntry *GetNext(DescEntry *de);
		DescEntry *GetDown(DescEntry *de);
		void GetDescEntry(DescEntry *de,const BaseContainer **bc,DescID &descid);

		SubDialog *CreateDialog();
		void FreeDialog(SubDialog *dlg);

		Bool CreatePopupMenu(BaseContainer &menu);
		Bool GetPopupId(LONG id,const DescID &descid);

		Bool CheckDescID(const DescID &searchid,const AtomArray &ops,DescID *completeid);
		Bool GetSubDescriptionWithData(const DescID &did,const AtomArray &op,RESOURCEDATATYPEPLUGIN  *resdatatypeplugin,const BaseContainer &bc,DescID *singledescid);

		DescID *GetSingleDescID();
		void SetSingleDescriptionMode(const DescID &descid);
};

class DynamicDescription
{
		DynamicDescription();

	public:

		DescID								Alloc(const BaseContainer &datadescription);
		Bool									Set(const DescID &descid,const BaseContainer &datadescription);
		const BaseContainer*	Find(const DescID &descid);
		Bool									Remove(const DescID &descid);

		Bool									CopyTo(DynamicDescription *dest);

		void*									BrowseInit(void);
		Bool									BrowseGetNext(void* handle,DescID *id,const BaseContainer **data);
		void									BrowseFree(void* &handle);

		Bool									FillDefaultContainer(BaseContainer &res,LONG type,const String &name);
};
#else
	#include "res_basecontainer.h"
#endif

#define HandleDescGetVector(tid,vector,t_data,flags) \
	switch (tid[1].id) \
	{ \
		case 0:			t_data = GeData(vector);   flags |= DESCFLAGS_PARAM_GET; break; \
		case 1000:	t_data = GeData(vector.x); flags |= DESCFLAGS_PARAM_GET; break; \
		case 1001:	t_data = GeData(vector.y); flags |= DESCFLAGS_PARAM_GET; break; \
		case 1002:	t_data = GeData(vector.z); flags |= DESCFLAGS_PARAM_GET; break; \
	} \

#define HandleDescSetVector(v,tid,vector,t_data,flags) \
	switch (tid[1].id) \
	{ \
		case 0:			v = t_data.GetVector(); flags |= DESCFLAGS_PARAM_SET; break; \
		case 1000:	v = Vector(t_data.GetReal(),vector.y,vector.z); flags |= DESCFLAGS_PARAM_SET; break; \
		case 1001:	v = Vector(vector.x,t_data.GetReal(),vector.z); flags |= DESCFLAGS_PARAM_SET; break; \
		case 1002:	v = Vector(vector.x,vector.y,t_data.GetReal()); flags |= DESCFLAGS_PARAM_SET; break; \
	} \

struct DescriptionCommand
{
	DescID id;
};

struct DescriptionCheckDragAndDrop
{
	DescID			id;
	BaseList2D	*element;
	Bool				result;

	DescriptionCheckDragAndDrop() { result = TRUE; }
};

struct DescriptionGetBitmap
{
	DescID			id;
	BaseBitmap	*bmp;
};

// public stuff
Bool Description_Register(LONG id,const String &idstr,LocalResource *res);


// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF

#define LIBRARY_DESCRIPTIONLIB		1000467

struct DescriptionLib : public C4DLibrary
{
	Bool (*Register )(LONG id,const String &idstr,LocalResource *res);

	Description*					(*Alloc)();
	void									(*Free)(Description *&description);

	Bool									(*LoadDescriptionBc)(Description *desc,const BCResourceObj *bc,Bool copy);
	Bool									(*LoadDescriptionId)(Description *desc,LONG id);
	Bool									(*LoadDescriptionStr)(Description *desc,const String *id);
	Bool									(*SortGroups)(Description *desc);

	const BCResourceObj*	(*GetDescription)(Description *desc);
	const BaseContainer*	(*GetParameter)(Description *desc,const DescID &id,BaseContainer &temp,AtomArray *ar);
	BaseContainer*				(*GetParameterI)(Description *desc,const DescID &id,AtomArray *ar);
	Bool									(*SetParameter)(Description *desc,const DescID &id,const BaseContainer &param,const DescID &groupid);	// returns the specified property

	void *								(*BrowseInit)(Description *desc);
	Bool									(*GetNext)(Description *desc,void *handle,const BaseContainer **bc,DescID &id,DescID &groupid);
	void									(*BrowseFree)(Description *desc,void *&handle);
	void									(*EX_01)(Description *desc);

	SubDialog *						(*CreateDialog)(Description *desc);
	void									(*FreeDialog)(Description *desc,SubDialog *dlg);

	Bool									(*CreatePopupMenu)(Description *desc,BaseContainer *menu);
	Bool									(*GetPopupId)(Description *desc,LONG id,const DescID &descid);

	DescID*								(*GetSingleDescID)(Description *desc);
	void									(*SetSingleDescriptionMode)(Description *desc,const DescID &descid);

	void									(*DescID_Init)(DescID *id);
	void									(*DescID_Free)(DescID *id);
	void									(*DescID_SetId)(DescID *id,const DescLevel &subid);
	void									(*DescID_PushId)(DescID *id,const DescLevel &subid);
	void									(*DescID_PopId)(DescID *id);
	const DescLevel&			(*DescID_operator1)(DescID *id,LONG pos);
	const DescID					(*DescID_operator2)(DescID *id,LONG pos);
	void									(*DescID_CopyTo)(DescID *src,DescID *dest);
	Bool									(*DescID_Compare)(DescID *d1,DescID *d2);

	DescID								(DynamicDescription::*DDAlloc					)(const BaseContainer &datadescription);
	Bool									(DynamicDescription::*DDSet						)(const DescID &descid,const BaseContainer &datadescription);
	const BaseContainer*	(DynamicDescription::*DDFind					)(const DescID &descid);
	Bool									(DynamicDescription::*DDRemove				)(const DescID &descid);
	Bool									(DynamicDescription::*DDCopyTo				)(DynamicDescription *dest);
	void*									(DynamicDescription::*DDBrowseInit		)(void);
	Bool									(DynamicDescription::*DDBrowseGetNext	)(void* handle,DescID *id,const BaseContainer **data);
	void									(DynamicDescription::*DDBrowseFree		)(void* &handle);
	Bool									(DynamicDescription::*FillDefaultContainer)(BaseContainer &res,LONG type,const String &name);

	Bool									(*GetSubDescriptionWithData						)(Description *desc,const DescID &did,const AtomArray &op,RESOURCEDATATYPEPLUGIN *resdatatypeplugin,const BaseContainer &bc,DescID *singledescid);
	Bool									(*CheckDescID													)(Description *desc,const DescID &searchid,const AtomArray &ops,DescID *completeid);

	DescEntry*						(*DescEntryGetFirst										)(Description *desc,const AtomArray &op);
	DescEntry*						(*DescEntryGetNext										)(Description *desc,DescEntry *de);
	DescEntry*						(*DescEntryGetDown										)(Description *desc,DescEntry *de);
	void									(*DescEntryGetDescEntry								)(Description *desc,DescEntry *de,const BaseContainer **bc,DescID &descid);
};

// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF

#endif
