#include "c4d_objectplugin.h"
#include "c4d_memory.h"
#include "c4d_general.h"

#ifdef __API_INTERN__
	#include "operatingsystem.h"
	#include "c4d_resource.h"
	#include "basedraw.h"
	#include "res_colortab_priv.h"
#else
	#include "c4d_tools.h"
	#include "c4d_basebitmap.h"
	#include "c4d_file.h"
	#include "c4d_resource.h"
	#include "c4d_baseobject.h"
	#include "c4d_basedraw.h"
	#include "dbasedraw.h"
#endif

void ObjectData::GetDimension(BaseObject *op, Vector *mp, Vector *rad) 
{
}

Bool ObjectData::Draw(BaseObject *op, LONG drawpass, BaseDraw *bd, BaseDrawHelp *bh) 
{ 
	if (drawpass!=DRAWPASS_HANDLES) return TRUE;

	LONG	 i,pass;
	Vector p;
	LONG   cnt = GetHandleCount(op);
	if (!cnt) return TRUE;

	#ifdef __API_INTERN__
		LONG hitid = C4DOS.Bo->GetHighlightHandle(op,bd);
		Matrix mg=bh->m;
	#else
		LONG hitid = op->GetHighlightHandle(bd);
		Matrix mg=bh->GetMg();
	#endif
	Vector col1 = GetViewColor(VIEWCOLOR_SELECTION_PREVIEW);
	Vector col2 = GetViewColor(VIEWCOLOR_ACTIVEPOINT);

	for (pass=0; pass<2; pass++)
	{
		if (pass==0)
			bd->SetPen(col2);
		else
			bd->SetPen(col1);

		for (i=0; i<cnt; i++)
		{
			if ((i==hitid)!=pass) continue;
			p = GetHandle(op,i);
			if (p.x>=GETHANDLE_INVALID_HANDLE) continue;
			p*=mg;
			bd->Handle3D(p,HANDLE_BIG);

			#ifndef __API_INTERN__
				bd->Line3D(Vector(0.0,0.0,0.0)*mg,p);
			#endif
		}
	}

	return TRUE;
}

Vector ObjectData::GetHandle(BaseObject *op, LONG i)
{
	return 0.0;
}

void ObjectData::SetHandle(BaseObject *op, LONG i, Vector p)
{
}

LONG ObjectData::GetHandleCount(BaseObject *op)
{
	return 0;
}

LONG ObjectData::DetectHandle(BaseObject *op, BaseDraw *bd, LONG x, LONG y, LONG qualifier)
{
	if (qualifier&QUALIFIER_CTRL) return NOTOK;

	Matrix	mg = op->GetMg();
	LONG    i,ret=NOTOK;
	Vector	p;

	for (i=0; i<GetHandleCount(op); i++)
	{
		p = GetHandle(op,i);
		if (p.x>=GETHANDLE_INVALID_HANDLE) continue;

		if (bd->PointInRange(p*mg,x,y)) 
		{
			ret=i;
			if (!(qualifier&QUALIFIER_SHIFT)) break;
		}
	}
	return ret;
}

Bool ObjectData::MoveHandle(BaseObject *op, BaseObject *undo, const Matrix &tm, LONG hit_id, LONG qualifier) 
{ 
	Vector p = ((ObjectData*)undo->GetNodeData())->GetHandle(undo,hit_id);
	SetHandle(op,hit_id,tm*p);

	return TRUE;
}

SplineObject* ObjectData::GetContour(BaseObject *op, BaseDocument *doc, Real lod, BaseThread *bt) 
{ 
	return NULL; 
}

BaseObject* ObjectData::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh) 
{ 
	return NULL; 
}

Bool ObjectData::ModifyObject(BaseObject *op, BaseDocument *doc, BaseObject *mod, const Matrix &op_mg, const Matrix &mod_mg, Real lod, LONG flags, BaseThread *thread) 
{ 
	return TRUE; 
}

void ObjectData::CheckDirty(BaseObject *op, BaseDocument *doc) 
{
}

void ObjectData::ModifyParticles(BaseObject *op, Particle *pp, BaseParticle *ss, LONG pcnt, Real diff)
{
}

void ObjectData::GetModelingAxis(BaseObject *op, BaseDocument *doc, Matrix &axis)
{
}

Bool ObjectData::AddToExecution(BaseObject *op, PriorityList *list)
{
	return FALSE;
}

LONG ObjectData::Execute(BaseObject *op, BaseDocument *doc, BaseThread *bt, LONG priority, LONG flags)
{
	return EXECUTION_RESULT_OK;
}

static void FillObjectPlugin(OBJECTPLUGIN *np, DataAllocator *npalloc, LONG info, LONG disklevel, BaseBitmap *icon, void *emulation)
{
	FillNodePlugin(np,info,npalloc,icon,disklevel,emulation);

	np->command_icon				= icon;
	np->GetDimension				= &ObjectData::GetDimension;
	np->Draw								= &ObjectData::Draw;
	np->DetectHandle				= &ObjectData::DetectHandle;
	np->MoveHandle					= &ObjectData::MoveHandle;
	np->Execute							= &ObjectData::Execute;
	np->AddToExecution			= &ObjectData::AddToExecution;
	np->GetModelingAxis			= &ObjectData::GetModelingAxis;
}

Bool RegisterObjectPlugin(LONG id, const String &str, LONG info, DataAllocator *g, const String &description, LONG disklevel)
{
	return RegisterObjectPlugin(id,str,info,g,description,NULL,disklevel,NULL);
}

#ifndef __API_INTERN__
Bool RegisterObjectPlugin(LONG id, const String &str, LONG info, DataAllocator *npalloc, const String &description, String icon, LONG disklevel)
{
	Bool ok=FALSE;

	if (icon.Content())
	{
		AutoAlloc<BaseBitmap> icon1;
		if (icon1 && icon1->Init(GeGetPluginPath()+String("res")+icon)==IMAGE_OK)
			ok=RegisterObjectPlugin(id,str,info,npalloc,description,icon1,disklevel);
	}
	else
		ok=RegisterObjectPlugin(id,str,info,npalloc,description,NULL,disklevel,NULL);

	return ok;
}
#endif

Bool RegisterObjectPlugin(LONG id, const String &str, LONG objectinfo, DataAllocator *npalloc, const String &description, BaseBitmap *icon, LONG disklevel, void *emulation)
{
	if (description.Content() && !RegisterDescription(id,description)) return FALSE;

	OBJECTPLUGIN np;
	ClearMem(&np,sizeof(np));
	FillObjectPlugin(&np,npalloc,objectinfo,disklevel,icon,emulation);

	np.CheckDirty		= &ObjectData::CheckDirty;

	if (objectinfo&OBJECT_MODIFIER)
		np.ModifyObject	= &ObjectData::ModifyObject;

	if (objectinfo&OBJECT_PARTICLEMODIFIER)
		np.ModifyParticles = &ObjectData::ModifyParticles;
	
	if (objectinfo&OBJECT_ISSPLINE) 
		np.GetContour = &ObjectData::GetContour;
	
	if (objectinfo&OBJECT_GENERATOR) 
		np.GetVirtualObjects = &ObjectData::GetVirtualObjects;

	return GeRegisterPlugin(C4DPL_OBJECT,id,str,&np,sizeof(np));
}
