
#include "lib_description.h"


#define LIBID			LIBRARY_DESCRIPTIONLIB
#define LIB				DescriptionLib


static LIB *library = NULL;


static LIB *CheckLibObjectList(LONG offset)
{
	return (LIB*)CheckLib(LIBID,offset,(C4DLibrary**)&library);
}





Bool DescLevel::operator == (const DescLevel &d) const
{
	if (d.id != id) return FALSE;

	if (d.dtype && dtype && d.dtype!=dtype) return FALSE;
	if (d.creator  && creator  && d.creator !=creator ) return FALSE;

	return TRUE;
}

Bool DescLevel::operator != (const DescLevel &d) const
{
	return !(*this==d);
}

LONG DescID::GetDepth() const
{
	LONG i=0;
	for (;(*this)[i].id!=0;i++) { }
	return i;
}

// checks if 'this' is part of 'cmp'
Bool DescID::IsPartOf(const DescID &cmp,LONG *pos) const
{
	LONG i;
	for (i=0;(*this)[i].id!=0;i++)
	{
		if ((*this)[i].id!=cmp[i].id)
			break;
	}
	if (pos) *pos = i;
	return i>0 && (*this)[i].id==0;
}

Bool Description_Register(LONG id,const String &idstr,LocalResource *res)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,Register)); if (!lib || !lib->Register) return FALSE;
	return lib->Register(id,idstr,res);
}

#ifndef __API_INTERN__

DescID::DescID()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_Init)); if (!lib || !lib->DescID_Init) return;
	lib->DescID_Init(this);
}

DescID::DescID(const DescID &src)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_Init)); if (!lib || !lib->DescID_Init) return;
	lib->DescID_Init(this);
	*this = src;
}

DescID::DescID(const DescLevel &id1)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_Init)); if (!lib || !lib->DescID_Init) return;
	lib->DescID_Init(this);
	SetId(id1);
}

DescID::DescID(const DescLevel &id1,const DescLevel &id2)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_Init)); if (!lib || !lib->DescID_Init) return;
	lib->DescID_Init(this);
	SetId(id1);
	PushId(id2);
}

DescID::DescID(const DescLevel &id1,const DescLevel &id2,const DescLevel &id3)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_Init)); if (!lib || !lib->DescID_Init) return;
	lib->DescID_Init(this);
	SetId(id1);
	PushId(id2);
	PushId(id3);
}

DescID::~DescID()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_Free)); if (!lib || !lib->DescID_Free) return;
	lib->DescID_Free(this);
}

void DescID::SetId(const DescLevel &subid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_SetId)); if (!lib || !lib->DescID_SetId) return;
	lib->DescID_SetId(this,subid);
}

void DescID::PushId(const DescLevel &subid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_PushId)); if (!lib || !lib->DescID_PushId) return;
	lib->DescID_PushId(this,subid);
}

void DescID::PopId()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_PopId)); if (!lib || !lib->DescID_PopId) return;
	lib->DescID_PopId(this);
}

DescLevel fallbacklevel(0);

const DescLevel &DescID::operator[] (LONG pos) const
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_operator1)); if (!lib || !lib->DescID_operator1) return fallbacklevel;
	return lib->DescID_operator1((DescID*)this,pos);
}

const DescID DescID::operator<< (LONG shift) const
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_operator2)); if (!lib || !lib->DescID_operator2) return fallbacklevel;
	return lib->DescID_operator2((DescID*)this,shift);
}

const DescID& DescID::operator = (const DescID &id)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_CopyTo)); if (!lib || !lib->DescID_CopyTo) return *this;
	lib->DescID_CopyTo((DescID*)&id,(DescID*)this);
	return *this;
}

Bool DescID::operator == (const DescID &d) const
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_CopyTo)); if (!lib || !lib->DescID_Compare) return 0;
	return lib->DescID_Compare((DescID*)&d,(DescID*)this);
}

Bool DescID::operator != (const DescID &d) const
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescID_CopyTo)); if (!lib || !lib->DescID_Compare) return TRUE;
	return !lib->DescID_Compare((DescID*)&d,(DescID*)this);
}

#ifndef __API_INTERN__


Description::Description()
{
}

Description *Description::Alloc()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,Alloc)); if (!lib || !lib->Alloc) return FALSE;
	return lib->Alloc();
}

void Description::Free(Description *&description)
{
	if (!description) return;
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,Free)); if (!lib || !lib->Free) return;
	lib->Free(description);
	description=NULL;
}

Bool Description::LoadDescription(const BCResourceObj *bc,Bool copy)
{
	if (!bc) return FALSE;
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,LoadDescriptionBc)); if (!lib || !lib->LoadDescriptionBc) return FALSE;
	return lib->LoadDescriptionBc(this,bc,copy);
}

Bool Description::LoadDescription(LONG id)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,LoadDescriptionId)); if (!lib || !lib->LoadDescriptionId) return FALSE;
	return lib->LoadDescriptionId(this,id);
}

Bool Description::LoadDescription(const String &id)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,LoadDescriptionStr)); if (!lib || !lib->LoadDescriptionStr) return FALSE;
	return lib->LoadDescriptionStr(this,&id);
}

Bool Description::SortGroups()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,SortGroups)); if (!lib || !lib->SortGroups) return FALSE;
	return lib->SortGroups(this);
}

const BCResourceObj* Description::GetDescription()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetDescription)); if (!lib || !lib->GetDescription) return NULL;
	return lib->GetDescription(this);
}

const BaseContainer* Description::GetParameter(const DescID &id,BaseContainer &temp,AtomArray *ar)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetParameter)); if (!lib || !lib->GetParameter) return NULL;
	return lib->GetParameter(this,id,temp,ar);
}

BaseContainer* Description::GetParameterI(const DescID &id,AtomArray *ar)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetParameterI)); if (!lib || !lib->GetParameterI) return NULL;
	return lib->GetParameterI(this,id,ar);
}

Bool Description::SetParameter(const DescID &id,const BaseContainer &param,const DescID &groupid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetParameter)); if (!lib || !lib->SetParameter) return NULL;
	return lib->SetParameter(this,id,param,groupid);
}

void *Description::BrowseInit()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,BrowseInit)); if (!lib || !lib->BrowseInit) return FALSE;
	return lib->BrowseInit(this);
}

Bool Description::GetNext(void *handle,const BaseContainer **bc,DescID &id,DescID &groupid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetNext)); if (!lib || !lib->GetNext) return FALSE;
	return lib->GetNext(this,handle,bc,id,groupid);
}

void Description::BrowseFree(void *&handle)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,BrowseFree)); if (!lib || !lib->BrowseFree) return;
	lib->BrowseFree(this,handle);
}

SubDialog *Description::CreateDialog()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,CreateDialog)); if (!lib || !lib->CreateDialog) return FALSE;
	return lib->CreateDialog(this);
}

void Description::FreeDialog(SubDialog *dlg)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,FreeDialog)); if (!lib) return;
	lib->FreeDialog(this,dlg);
}

Bool Description::CreatePopupMenu(BaseContainer &menu)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,CreatePopupMenu)); if (!lib) return FALSE;
	return lib->CreatePopupMenu(this,&menu);
}

Bool Description::GetPopupId(LONG id,const DescID &descid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetPopupId)); if (!lib) return FALSE;
	return lib->GetPopupId(this,id,descid);
}

DescID* Description::GetSingleDescID()
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetSingleDescID)); if (!lib) return NULL;
	return lib->GetSingleDescID(this);
}

void Description::SetSingleDescriptionMode(const DescID &descid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,SetSingleDescriptionMode)); if (!lib) return;
	lib->SetSingleDescriptionMode(this,descid);
}

Bool Description::GetSubDescriptionWithData(const DescID &did,const AtomArray &op,RESOURCEDATATYPEPLUGIN *resdatatypeplugin,const BaseContainer &bc,DescID *singledescid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,GetSubDescriptionWithData)); if (!lib) return FALSE;
	return lib->GetSubDescriptionWithData(this,did,op,resdatatypeplugin,bc,singledescid);
}

Bool Description::CheckDescID(const DescID &searchid,const AtomArray &ops,DescID *completeid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,CheckDescID)); if (!lib) return FALSE;
	return lib->CheckDescID(this,searchid,ops,completeid);
}

DescEntry* Description::GetFirst(const AtomArray &op)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescEntryGetFirst)); if (!lib) return FALSE;
	return lib->DescEntryGetFirst(this,op);
}

DescEntry* Description::GetNext(DescEntry *de)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescEntryGetNext)); if (!lib) return FALSE;
	return lib->DescEntryGetNext(this,de);
}

DescEntry* Description::GetDown(DescEntry *de)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescEntryGetDown)); if (!lib) return FALSE;
	return lib->DescEntryGetDown(this,de);
}

void Description::GetDescEntry(DescEntry *de,const BaseContainer **bc,DescID &descid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DescEntryGetDescEntry)); if (!lib) return;
	lib->DescEntryGetDescEntry(this,de,bc,descid);
}



DescID DynamicDescription::Alloc(const BaseContainer &datadescription)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDAlloc)); if (!lib || !lib->DDAlloc) return DescLevel(0);
	return (this->*lib->DDAlloc)(datadescription);
}

Bool DynamicDescription::Set(const DescID &descid,const BaseContainer &datadescription)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDSet)); if (!lib || !lib->DDSet) return FALSE;
	return (this->*lib->DDSet)(descid,datadescription);
}

const BaseContainer* DynamicDescription::Find(const DescID &descid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDFind)); if (!lib || !lib->DDFind) return FALSE;
	return (this->*lib->DDFind)(descid);
}

Bool DynamicDescription::Remove(const DescID &descid)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDRemove)); if (!lib || !lib->DDRemove) return FALSE;
	return (this->*lib->DDRemove)(descid);
}

Bool DynamicDescription::CopyTo(DynamicDescription *dest)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDCopyTo)); if (!lib || !lib->DDCopyTo) return FALSE;
	return (this->*lib->DDCopyTo)(dest);
}

void* DynamicDescription::BrowseInit(void)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDBrowseInit)); if (!lib || !lib->DDBrowseInit) return FALSE;
	return (this->*lib->DDBrowseInit)();
}

Bool DynamicDescription::BrowseGetNext(void* handle,DescID *id,const BaseContainer **data)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDBrowseGetNext)); if (!lib || !lib->DDBrowseGetNext) return FALSE;
	return (this->*lib->DDBrowseGetNext)(handle,id,data);
}

void DynamicDescription::BrowseFree(void* &handle)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,DDBrowseFree)); if (!lib || !lib->DDBrowseFree) return;
	(this->*lib->DDBrowseFree)(handle);
}

Bool DynamicDescription::FillDefaultContainer(BaseContainer &res,LONG type,const String &name)
{
	LIB *lib = CheckLibObjectList(LIBOFFSET(LIB,FillDefaultContainer)); if (!lib || !lib->FillDefaultContainer) return FALSE;
	return (this->*lib->FillDefaultContainer)(res,type,name);
}

#endif

#endif

