/////////////////////////////////////////////////////////////
// CINEMA SDK : GRAPHVIEW				 													 //
/////////////////////////////////////////////////////////////
// VERSION		: CINEMA 4D V8 OXYGEN												 //
/////////////////////////////////////////////////////////////
// (c) 1989-2002 MAXON Computer GmbH, all rights reserved	 //
/////////////////////////////////////////////////////////////

#include "c4d_graphview.h"
#include "c4d_operatordata.h"
#include "c4d_particles.h"

////////////////////////////////

const String GvGetOperatorDetailedText(GvOperatorData *op, GvNode *bn)
{
	String text = op->GetText(bn);
	if (text.Content()) text = String(" (") + text + String(")");
	return bn->GetTitle() + text;
}

const String GvGetOperatorTitle(GvNode *bn, LONG string_id)
{
	String title = bn->GetName(); return title.Content() ? title : GeLoadString(string_id);
}

////////////////////////////////

Bool GvGetPortDescription(GvPortsDescInfo *info, GvPortIO port, LONG id, GvPortDescription *pd)
{
	LONG i;

	if (info)
	{
		if (port == GV_PORT_INPUT || port == GV_PORT_INPUT_OR_GEDATA)
		{
			for (i = 0; i < info->in.count; ++i)
			{
				if (info->in.ids[i] == id)
				{
					if (info->in.name_ids) pd->name = GeLoadString(info->in.name_ids[i]);
					else if (info->in.names) pd->name = *info->in.names[i];
					else pd->name = String();
					pd->data_id = info->in.types[i];
					pd->flags = (GvPortDescFlags)info->in.flags[i];
					pd->parent_id = GV_PORT_INVALID_ID;
					return TRUE;
				}		
			}
		}
		else if (port == GV_PORT_OUTPUT)
		{
			for (i = 0; i < info->out.count; ++i)
			{
				if (info->out.ids[i] == id)
				{
					if (info->out.name_ids) pd->name = GeLoadString(info->out.name_ids[i]);
					else if (info->out.names) pd->name = *info->out.names[i];
					else pd->name = String();
					pd->data_id = info->out.types[i];
					pd->flags = (GvPortDescFlags)info->out.flags[i];
					pd->parent_id = GV_PORT_INVALID_ID;
					return TRUE;
				}		
			}
		}
	}
	return FALSE;
}

////////////////////////////////

void GvFreeValuesTable(GvNode *bn, GvValue **&ports, LONG &nr_of_ports)
{
	if (ports)
	{
		LONG i;
		for (i = 0; i < nr_of_ports; ++i)
		{
			if (ports[i])
			{
				bn->FreeCalculationHandler(ports[i]);
				ports[i] = NULL;
			}
		}
		bDelete(ports);
	}
	nr_of_ports = 0;
}

void GvFreeValuesTable(GvNode *bn, GvValuesInfo &info)
{
	if (!bn) return;

	if (info.in_values)
	{
		LONG i;
		for (i = 0; i < info.nr_of_in_values; ++i)
		{
			if (info.in_values[i])
			{
				bn->FreeCalculationHandler(info.in_values[i]);
				info.in_values[i] = NULL;
			}
		}
	}
	bDelete(info.in_values);
	info.nr_of_in_values = 0;
	bDelete(info.out_ports);
	info.nr_of_out_ports = 0;
}

Bool GvBuildInValuesTable(GvNode *bn, GvValue **&ports, LONG &nr_of_ports, GvCalc *c, GvRun *r, GvIdTablePtr ids)
{
	LONG i, entries = 0; GvPortDescription pd; GvPortListEntry *entry; Bool valid; GvPort *port;

	nr_of_ports = 0;

	if (ids == GV_EXISTING_PORTS)
	{
		entries = bn->GetInPortCount();
		if (!entries) { ports = NULL; return TRUE; }

		ports = bNew GvValue*[entries]; if (!ports) goto Error;
		for (i = 0; i < entries; ++i) ports[i] = NULL;

		for (i = 0; i < entries; ++i)
		{
			GvPort *port = bn->GetInPort(i); if (!port) goto Error;
			ports[i] = bn->AllocCalculationHandler(port->GetMainID(),c,r,i);
			if (!ports[i]) goto Error;
		}
	}
	else if (ids == GV_DEFINED_PORTS)
	{
		AutoAlloc<GvPortList> portlist; if (!portlist) return FALSE;
		bn->GetPortList(GV_PORT_INPUT,portlist);
		entries = portlist->GetCount();
		if (!entries) { ports = NULL; return TRUE; }

		ports = bNew GvValue*[entries]; if (!ports) goto Error;
		for (i = 0; i < entries; ++i) ports[i] = NULL;

		for (i = 0; i < entries; ++i)
		{	
			entry = portlist->GetIndex(i);
			if (!entry || !bn->GetPortDescription(GV_PORT_INPUT,entry->id,&pd)) goto Error;
			port = bn->GetInPortFirstMainID(entry->id);
			if (!port && pd.ports_min > 0) goto Error;

			valid = pd.flags & GV_PORTDESCRIPTION_MULTIPLE ?  port != NULL : TRUE;
			if (valid)
			{
				ports[i] = bn->AllocCalculationHandler(entry->id,c,r,GV_MULTIPLE_PORTS);
				if (!ports[i]) goto Error;
			}
		}
	}
	else
	{
		for (entries = 0; ids[entries];) ++entries;
		if (!entries) { ports = NULL; return TRUE; }

		ports = bNew GvValue*[entries]; if (!ports) goto Error;
		for (i = 0; i < entries; ++i) ports[i] = NULL;
		
		for (i = 0; i < entries; ++i)
		{	
			if (!bn->GetPortDescription(GV_PORT_INPUT,ids[i],&pd)) goto Error;
			port = bn->GetInPortFirstMainID(ids[i]);
			if (!port && pd.ports_min > 0) goto Error;

			valid = pd.flags & GV_PORTDESCRIPTION_MULTIPLE ?  port != NULL : TRUE;
			if (valid)
			{
				ports[i] = bn->AllocCalculationHandler(ids[i],c,r,GV_MULTIPLE_PORTS);
				if (!ports[i]) goto Error;
			}
		}
	}
	nr_of_ports = entries;
	return TRUE;

Error:
	GvFreeValuesTable(bn,ports,entries);
	return FALSE;
}

Bool GvCalculateInValuesTable(GvNode *bn, GvRun *run, GvCalc *calc, GvValuesInfo &info, LONG singleport, BaseTime *time)
{
	LONG i;

	if (info.in_values)
	{
		for (i = 0; i < info.nr_of_in_values; ++i)
		{
			if (info.in_values[i])
			{
				if (!info.in_values[i]->Calculate(bn,GV_PORT_INPUT,run,calc,singleport,time)) return FALSE;
			}
		}
	}
	return TRUE;
}
															
Bool GvBuildOutPortsTable(GvNode *bn, GvPort **&ports, LONG &nr_of_ports)
{
	LONG i, j = bn->GetOutPortCount();
	if (!j) { ports = NULL; return TRUE; }
	ports = bNew GvPort*[j]; if (!ports) goto Error;
	for (i = 0; i < j; ++i)
	{
		ports[i] = bn->GetOutPort(i); if (!ports[i]) goto Error;
	}
	nr_of_ports = j;
	return TRUE;

Error:
	bDelete(ports);
	nr_of_ports = 0;
	return FALSE;
}

////////////////////////////////

GvWorld*						GvGetWorld(void) { return C4DOS.Gv->globals->GetWorld(); }
const	String				GvGetEmptyString(void) { return C4DOS.Gv->globals->GetEmptyString(); }
const String				GvGetErrorString(const String &command, LONG err) { return C4DOS.Gv->globals->GetErrorString(command,err); } 
void								GvGetPortList(GvPortsDescInfo *info, GvPortIO port, GvPortList &portlist) { C4DOS.Gv->globals->GetPortList(info,port,portlist); }
Bool								GvGetAllDataTypes(GvPortDescInfo *info, ULONG default_flag, LONG first_id) { return C4DOS.Gv->globals->GetAllDataTypes(info,default_flag,first_id); }
void								GvFreePortDescInfo(GvPortDescInfo *info) { if (C4DOS.Gv->globals->FreePortDescInfo) C4DOS.Gv->globals->FreePortDescInfo(info); } // Thinking Safety Check
Bool								GvRegisterValueType(GV_VALUE_HANDLER *data, LONG struct_size) { return C4DOS.Gv->globals->RegisterValueType(data,struct_size); }
Bool								GvRegisterDataType(GV_DATA_HANDLER *data, LONG struct_size, const char *symbol) { return C4DOS.Gv->globals->RegisterDataType(data,struct_size,symbol); }
Bool								GvRegisterValGroupType(GV_VALGROUP_HANDLER *data, LONG struct_size) { return C4DOS.Gv->globals->RegisterValGroupType(data,struct_size); }
Bool								GvRegisterOpClassType(GV_OPCLASS_HANDLER *data, LONG struct_size) { return C4DOS.Gv->globals->RegisterOpClassType(data,struct_size); }
Bool								GvRegisterOpGroupType(GV_OPGROUP_HANDLER *data, LONG struct_size) { return C4DOS.Gv->globals->RegisterOpGroupType(data,struct_size); }
GV_OPCLASS_HANDLER* GvFindRegisteredOpClass(GvOpClassID id) { return C4DOS.Gv->globals->FindRegisteredOpClass(id); }
GV_OPGROUP_HANDLER* GvFindRegisteredOpGroup(GvOpGroupID id) { return C4DOS.Gv->globals->FindRegisteredOpGroup(id); }
Bool								GvLoadIcon(BaseBitmap *&bm, const String &name) { return C4DOS.Gv->globals->LoadIcon(bm,name); }

////////////////////////////////
