/* -----------------------------------------------------------------------------
*
*  nppy.c
*
*  ANTz - realtime 3D data visualization tools for the real-world, based on NPE.
*
*  ANTz is hosted at http://openantz.com and NPE at http://neuralphysics.org
*
*  Written in 2010-2016 by Shane Saxon - saxon@openantz.com
*
*  Please see main.c for a complete list of additional code contributors.
*
*  To the extent possible under law, the author(s) have dedicated all copyright 
*  and related and neighboring rights to this software to the public domain
*  worldwide. This software is distributed without any warranty.
*
*  Released under the CC0 license, which is GPL compatible.
*
*  You should have received a copy of the CC0 Public Domain Dedication along
*  with this software (license file named LICENSE.txt). If not, see
*  http://creativecommons.org/publicdomain/zero/1.0/
*
* --------------------------------------------------------------------------- */

#include "nppy.h"

#include "../npfile.h"
#include <Python.h>
#include "../net/npcurl.h"


//------------------------------------------------------------------------------

static PyObject *pModule = NULL;
static int numargs = 0;
static PyObject* asdf;

/*
void npPyBuildAntzDictionary(void* dataRef);
void npPyBuildAntzDictionary(void* dataRef)
{
	pData data = (pData) dataRef;
	int i = 0;
	char str[256] = {'\0'};
	PyRun_SimpleString("d = {}");
	while(data->map.typeMapNode[i].id != kNPsize)
	{
		sprintf(str, "d['%s'] = %d", data->map.typeMapNode[i].name, data->map.typeMapNode[i].id);
		PyRun_SimpleString(str);
		printf("str : %s\n", str);
		str[0] = '\0';
		i++;
	}
}
*/

static PyObject* np_PyBuildAntzDict(PyObject *self, PyObject *args)
{
	pData data = (pData)npGetDataRef();
	PyObject *d = PyDict_New();
	PyObject *key = NULL;
	PyObject *value = NULL;
	int i = 0;

	while(data->map.typeMapNode[i].id != kNPsize)
	{
		key = Py_BuildValue("s", data->map.typeMapNode[i].name);
		value = Py_BuildValue("i", data->map.typeMapNode[i].id);
		PyDict_SetItem(d, key, value);
		i++;
	}
	
	return d;
}

static PyObject* np_PyTagNodeWith(PyObject *self, PyObject *args)
{
	pData data = (pData)npGetDataRef();
	char* tagText = NULL;
	int nodeID = 0;
	int recordID = 0;
	int tableID = 0;
	pNPrecordTag rt = NULL;
	pNPnode node = NULL;
	// nodeID, recordID, tableID, tagText
	if(!PyArg_ParseTuple(args, "iiis", &nodeID, &recordID, &tableID, &tagText))
		return NULL;

	rt			   = npNewTag(data);
	rt->titleSize  = strlen(rt->title) + 1;
	rt->recordID   = recordID;
	rt->tableID    = tableID;
	sprintf(rt->title, "%s", tagText);

	node		   = npGetNodeByID(nodeID, data);
	node->recordID = rt->recordID;
	node->tableID  = rt->tableID;

	npTagSortAdd(rt, data);
	npTagNode(node, data);
	Py_RETURN_NONE;
}


static PyObject*
np_PyCurlGetRawResult(PyObject *self, PyObject *args)
{
	void* data = npGetDataRef();

	if( ((pData)data)->io.curl.raw != '\0' )
	{
		return Py_BuildValue("s", ((pData)data)->io.curl.raw);
	}

	Py_RETURN_NONE;
}

static PyObject*
np_PyCurlGetURL(PyObject *self, PyObject *args)
{
	pData data = npGetDataRef();
	char *url = NULL;
	if(!PyArg_ParseTuple(args, "s", &url))
		return NULL;

	printf("URL : %s\n", url);
	printf("responseSize : %d\n", data->io.curl.responseSize);
	printf("dataRef ptr : %p\n", data);
	printf("data->io.curl.raw : %p\n", data->io.curl.raw);
	data->io.curl.responseSize = 0;
	npCURLgetUrl(&data->io.curl, url, 0, data);
	

	Py_RETURN_NONE;
}

//void npNodeSetkNPubyteRGBA
void npNodeSetUbyteRGBA(int nodeID, int param, unsigned char r, unsigned char g, unsigned char b, unsigned char a, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPcolor:
			node->color.r = r;
			node->color.g = g;
			node->color.b = b;
			node->color.a = a;
			break;
	}
}

void npNodeGetUbyteRGBA(int nodeID, int param, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a, void* dataRef);
void npNodeGetUbyteRGBA(int nodeID, int param, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPcolor:
			(*r) = node->color.r;
			(*g) = node->color.g;
			(*b) = node->color.b;
			(*a) = node->color.a;
			/*
			node->color.r = r;
			node->color.g = g;
			node->color.b = b;
			node->color.a = a;
			*/
			break;
	}
}

void npNodeGetIntXYZ(int nodeID, int param, int* x, int* y, int* z, void* dataRef);
void npNodeGetIntXYZ(int nodeID, int param, int* x, int* y, int* z, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPauxA:
			printf("kNPauxA");
			(*x) = node->auxA.x;
			(*y) = node->auxA.y;
			(*z) = node->auxA.z;
			break;
		case kNPauxB:
			printf("kNPauxB");
			(*x) = node->auxB.x;
			(*y) = node->auxB.y;
			(*z) = node->auxB.z;
			break;
		case kNPtriggerHi:
			(*x) = node->triggerHi.x;
			(*y) = node->triggerHi.y;
			(*z) = node->triggerHi.z;
			break;
		case kNPtriggerLo:
			(*x) = node->triggerLo.x;
			(*y) = node->triggerLo.y;
			(*z) = node->triggerLo.z;
			break;
		case kNPproximityMode:
			(*x) = node->proximityMode.x;
			(*y) = node->proximityMode.y;
			(*z) = node->proximityMode.z;
			break;
		case kNPsegments:
			(*x) = node->segments.x;
			(*y) = node->segments.y;
			(*z) = node->segments.z;
			break;
	}
	
}

void npNodeSetIntXYZ(int nodeID, int param, int x, int y, int z, void* dataRef);
void npNodeSetIntXYZ(int nodeID, int param, int x, int y, int z, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPauxA:
			node->auxA.x = x;
			node->auxA.y = y;
			node->auxA.z = z;
			break;
		case kNPauxB:
			node->auxB.x = x;
			node->auxB.y = y;
			node->auxB.z = z;
			break;
		case kNPtriggerHi:
			node->triggerHi.x = x;
			node->triggerHi.y = y;
			node->triggerHi.z = z;
			break;
		case kNPtriggerLo:
			node->triggerLo.x = x;
			node->triggerLo.y = y;
			node->triggerLo.z = z;
			break;
		case kNPproximityMode:
			
			break;
		case kNPsegments:
			break;
	}
}

void npNodeSetFloatXYZ(int nodeID, int param, float x, float y, float z, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPauxA:
			node->auxA.x = x;
			node->auxA.y = y;
			node->auxA.z = z;
			break;
		case kNPauxB:
			node->auxB.x = x;
			node->auxB.y = y;
			node->auxB.z = z;
			break;
		case kNPscale:
			//printf("kNPscale : %f\n", x);
			node->scale.x = x;
			node->scale.y = y;
			node->scale.z = z;
			break;
		case kNPtranslate:
			node->translate.x = x;
			node->translate.y = y;
			node->translate.z = z;
			break;
		case kNPtagOffset:
			node->tagOffset.x = x;
			node->tagOffset.y = y;
			node->tagOffset.z = z;
			break;
		case kNProtateRate:
			node->rotateRate.x = x;
			node->rotateRate.y = y;
			node->rotateRate.z = z;
			break;
		case kNProtate:
			node->rotate.x = x;
			node->rotate.y = y;
			node->rotate.z = z;
			break;
		case kNPscaleRate:
			node->scaleRate.x = x;
			node->scaleRate.y = y;
			node->scaleRate.z = z;
			break;
		case kNPtranslateRate:
			node->translateRate.x = x;
			node->translateRate.y = y;
			node->translateRate.z = z;
			break;
		case kNPtranslateVec:
			node->translateVec.x = x;
			node->translateVec.y = y;
			node->translateVec.z = z;
			break;
		case kNPsetHi:
			node->setHi.x = x;
			node->setHi.y = y;
			node->setHi.z = z;
			break;
		case kNPsetLo:
			node->setLo.x = x;
			node->setLo.y = y;
			node->setLo.z = z;
			break;
		case kNPproximity:
			node->proximity.x = x;
			node->proximity.y = y;
			node->proximity.z = z;
			break;
		// case screen, world
	}
}

void npNodeGetFloatXYZ(int nodeID, int param, float *x, float *y, float *z, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPauxA:
			(*x) = node->auxA.x;
			(*y) = node->auxA.y;
			(*z) = node->auxA.z;
			break;
		case kNPauxB:
			(*x) = node->auxB.x;
			(*y) = node->auxB.y;
			(*z) = node->auxB.z;
			break;
		case kNPscale:
			//printf("kNPscale : %f\n", x);
			(*x) = node->scale.x;
			(*y) = node->scale.y;
			(*z) = node->scale.z;
			break;
		case kNPtranslate:
			(*x) = node->translate.x;
			(*y) = node->translate.y;
			(*z) = node->translate.z;
			break;
		case kNPtagOffset:
			(*x) = node->tagOffset.x;
			(*y) = node->tagOffset.y;
			(*z) = node->tagOffset.z;
			break;
		case kNProtateRate:
			(*x) = node->rotateRate.x;
			(*y) = node->rotateRate.y;
			(*z) = node->rotateRate.z;
			break;
		case kNProtate:
			(*x) = node->rotate.x;
			(*y) = node->rotate.y;
			(*z) = node->rotate.z;
			break;
		case kNPscaleRate:
			(*x) = node->scaleRate.x;
			(*y) = node->scaleRate.y;
			(*z) = node->scaleRate.z;
			break;
		case kNPtranslateRate:
			(*x) = node->translateRate.x;
			(*y) = node->translateRate.y;
			(*z) = node->translateRate.z;
			break;
		case kNPtranslateVec:
			(*x) = node->translateVec.x;
			(*y) = node->translateVec.y;
			(*z) = node->translateVec.z;
			break;
		case kNPsetHi:
			(*x) = node->setHi.x;
			(*y) = node->setHi.y;
			(*z) = node->setHi.z;
			break;
		case kNPsetLo:
			(*x) = node->setLo.x;
			(*y) = node->setLo.y;
			(*z) = node->setLo.z;
			break;
		case kNPproximity:
			(*x) = node->proximity.x;
			(*y) = node->proximity.y;
			(*z) = node->proximity.z;
			break;
		// case screen, world
	}
}


void npNodeSetInt(int nodeID, int param, int val, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);

	printf("npNodeSetInt\n");
	switch(param) {
		case kNPid:
			printf("kNPid\n");
			//(*val) = node->id;
			node->id = val;
			break;
		case kNPtype:
			//(*val) = node->type;
			node->type = val;
			break;
		case kNPselected:
			//(*val) = node->selected;
			node->selected = val;
			break;
//		case kNPparent:
//			break;
		case kNPbranchLevel:
			//(*val) = node->;
			node->branchLevel = val;
			break;
		//case kNPchildSize:
		//	break;
		case kNPchildIndex:
			//(*val) = node->childIndex;
			node->childIndex = val;
			break;
		case kNPchildCount:
			//(*val) = node->childCount;
			node->childCount = val;
			break;
		case kNPchInputID:
			//(*val) = node->chInputID;
			node->chInputID = val;
			break;
		case kNPchOutputID:
			//(*val) = node->chOutputID;
			node->chOutputID = val;
			break;
		case kNPchLastUpdated:
			//(*val) = node->chLastUpdated;
			node->chLastUpdated = val;
			break;
		case kNPaverage:
			//(*val) = node->average;
			node->average = val;
			break;
		case kNPinterval:
			//(*val) = node->interval;
			node->interval = val;
			break;
		case kNPshader:
			//(*val) = node->shader;
			node->shader = val;
			break;
		case kNPgeometry:
			//(*val) = node->geometry;
			printf("Setting Geometry : %d\n", val);
			node->geometry = val;
			break;
		case kNPcolorIndex:
			//(*val) = node->colorIndex;
			printf("Setting colorIndex : %d\n", val);
			printf("kNPtextureID : %d\n", kNPtextureID);
			node->colorIndex = val;
			switch(val)
			{
				case 0:
					node->color.r = 50;
					node->color.g = 101;
					node->color.b = 50;
					break;
				case 1:
					node->color.r = 0;
					node->color.g = 255;
					node->color.b = 0;
					break;
				case 2:
					node->color.r = 255;
					node->color.g = 0;
					node->color.b = 0;
					break;
				case 3:
					node->color.r = 0;
					node->color.g = 0;
					node->color.b = 255;
					break;
				case 4:
					node->color.r = 255;
					node->color.g = 255;
					node->color.b = 0;
					break;
				case 5:
					node->color.r = 152;
					node->color.g = 0;
					node->color.b = 255;
					break;
				case 6:
					node->color.r = 255;
					node->color.g = 168;
					node->color.b = 0;
					break;
				case 7:
					node->color.r = 0;
					node->color.g = 255;
					node->color.b = 255;
					break;
				case 8:
					node->color.r = 255;
					node->color.g = 0;
					node->color.b = 255;
					break;
				case 9:
					node->color.r = 0;
					node->color.g = 153;
					node->color.b = 0;
					break;
				case 10:
					// 185, 153, 102
					break;
				case 11:
					// 255, 180, 255
					break;
				case 12:
					// 0, 152, 255
					break;
				case 13:
					// 185, 255, 0
					break;
				case 14:
					// 152, 0, 0
					break;
				case 15:
					// 127, 127, 127
					break;
				case 16:
					// 127, 127, 255
					break;
				case 17:
					// 197, 82, 0
					break;
				case 18:
					// 0, 0 , 0
					break;
				case 19:
					// 255, 255, 255
					break;
			}

			break;
		case kNPtextureID:
			//(*val) = node->textureID;
			node->textureID = val;
			break;
		case kNPtopo:
			//(*val) = node->topo;
			node->topo = val;
			break;
		case kNPfacet:
			//(*val) = node->facet;
			node->facet = val;
			break;
		case kNPtagMode:
			//(*val) = node->tagMode;
			node->tagMode = val;
			break;
		case kNPformatID:
			//(*val) = node->formatID;
			node->formatID = val;
			break;
//		case kNPtableID:
//			break;
		case kNPrecordID:
			//(*val) = node->recordID;
			node->recordID = val;
			break;
		case kNPsize:
			//(*val) = node->size;
			node->size = val;
			break;
	}
}

void npNodeGetFloat(int nodeID, int param, float* val, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPcolorShift:
			(*val) = node->colorShift;
			break;
		case kNPlineWidth:
			(*val) = node->lineWidth;
			break;
		case kNPpointSize:
			(*val) = node->pointSize;
			break;
		case kNPratio:
			(*val) = node->ratio;
			break;
		default:
			printf("Default\n");
			break;
	}
}

void npNodeGetBool(int nodeID, int param, bool* bo, void* dataRef);
void npNodeGetBool(int nodeID, int param, bool* bo, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPhide:
			(*bo) = node->hide;
			break;
		case kNPfreeze:
			(*bo) = node->freeze;
			break;
	}
}

void npNodeGetInt(int nodeID, int param, int* val, void* dataRef);
void npNodeGetInt(int nodeID, int param, int* val, void* dataRef)
{
	pData data = (pData) dataRef;
	pNPnode node = NULL;
	node = npGetNodeByID(nodeID, dataRef);
	if(!node)
		return;

	switch(param) {
		case kNPid:
			printf("kNPid\n");
			(*val) = node->id;
			break;
		case kNPtype:
			(*val) = node->type;
			break;
		case kNPselected:
			(*val) = node->selected;
			break;
		case kNPparent:
			if(node->parent)
				(*val) = node->parent->id;
			else
				(*val) = 0;
			break;
		case kNPbranchLevel:
			(*val) = node->branchLevel;
			break;
		//case kNPchildSize:
		//	break;
		case kNPchildIndex:
			(*val) = node->childIndex;
			break;
		case kNPchildCount:
			(*val) = node->childCount;
			break;
		case kNPchInputID:
			(*val) = node->chInputID;
			break;
		case kNPchOutputID:
			(*val) = node->chOutputID;
			break;
		case kNPchLastUpdated:
			(*val) = node->chLastUpdated;
			break;
		case kNPaverage:
			(*val) = node->average;
			break;
		case kNPinterval:
			(*val) = node->interval;
			break;
		case kNPshader:
			(*val) = node->shader;
			break;
		case kNPgeometry:
			(*val) = node->geometry;
			break;
		case kNPcolorIndex:
			(*val) = node->colorIndex;
			break;
		case kNPtextureID:
			(*val) = node->textureID;
			break;
		case kNPtopo:
			(*val) = node->topo;
			break;
		case kNPfacet:
			(*val) = node->facet;
			break;
		case kNPtagMode:
			(*val) = node->tagMode;
			break;
		case kNPformatID:
			(*val) = node->formatID;
			break;
//		case kNPtableID:
//			break;
		case kNPrecordID:
			(*val) = node->recordID;
			break;
		case kNPsize:
			(*val) = node->size;
			break;
	}
}

static PyObject* np_PyNodeSet(PyObject *self, PyObject *args)
{
	pData data = npGetDataRef();
	pNPnode node = NULL;
	int nodeID = 0;
	int parameter = 0;
	int varType;
	float fVal = 0;
	float fValX = 0;
	float fValY = 0;
	float fValZ = 0;
	float fValA = 0;
	unsigned char r = '0';
	unsigned char g = '0';
	unsigned char b = '0';
	unsigned char a = '0';
	void* value = NULL;
	long intVal = 0;
//	PyObject object;

	// nodeId, parameter, value
	/*
	if(!PyArg_ParseTuple(args, "iiO", &nodeID, &parameter, &object))
	{
		printf("Nope");
		//return NULL;
	}
	*/
	
	if(!PyArg_ParseTuple(args, "iif|fff", &nodeID, &parameter, &fVal, &fValY, &fValZ, &fValA))
	{
		printf("Nope\n");
		return NULL;
	/*
		if(!PyArg_ParseTuple(args, "iicccc", &nodeID, &parameter, &r, &g, &b, &a))
		{
			printf("Nope\n");
			return NULL;
		}
	*/
	}
	
	/*
	if(!PyArg_ParseTuple(args, "iifff", &nodeID, &parameter, &fValX, &fValY, &fValZ))
	{
		printf("Nope 2\n");
		return NULL;
	}
	else
	{
		printf("Yes\n");
	}
*/
	//printf("fVal : %d\n", (int)fVal);
	//printf("Py_TYPE : %d\n", Py_TYPE(&object));
//	printf("PyObject_TYPE : %d\n", PyObject_Type(&object));

	printf("nodeID : %d \n parameter : %d \n", nodeID, parameter);
	node = npGetNodeByID(nodeID, data);

	varType = npNodeMapIDtoType(parameter, data);
	printf("varType : %d\n", varType);;
	switch(varType){
		case kNPint:
			//printf("kNPint\n");
			printf("kNPint : %d\n", (int)fVal);
		//	printf("intVal : %d\n", intVal);
			npNodeSetInt(nodeID, parameter, (int)fVal, data);
			break;
		case kNPintXYZ:
			printf("kNPintXYZ\n");
			npNodeSetIntXYZ(nodeID, parameter, (int)fVal, (int)fValY, (int)fValZ, data);
			break;
		case kNPfloatXYZ:
			printf("kNPfloatXYZ\n");
			npNodeSetFloatXYZ(nodeID, parameter, fVal, fValY, fValZ, data);
			break;
		case kNPubyteRGBA:
			printf("kNPubyteRGBA\n");
			npNodeSetUbyteRGBA(nodeID, parameter, (unsigned char)fVal, (unsigned char)fValY, (unsigned char)fValZ, (unsigned char)fValA, data);
			break;
	}

Py_RETURN_NONE;
}

static PyObject* np_PyNodeGet(PyObject *self, PyObject *args)
{
	pData data = npGetDataRef();
	PyObject* obj = NULL;
	pNPnode node = NULL;
	int nodeID = 0;
	int param = 0;
	int varType = 0;
	int val = 0;
	float fVal, fValY, fValZ = 0;
	unsigned char r,g,b,a = {'\0'};
	bool bo = false;
		
	if(!PyArg_ParseTuple(args, "ii", &nodeID, &param))
		return NULL;

	node = npGetNodeByID(nodeID, data);
	if(!node)
		Py_RETURN_NONE;

	if(param == 56)
	{
		printf("V\n");
	}

	if(param == 103)
	{
		printf("zxcv\n");
	}

	printf("Param : %d \n nodeID : %d \n\n", param, nodeID);
	varType = npNodeMapIDtoType(param, data);
	printf("varType : %d\n", varType);

	if(varType == kNPintXYZ)
	{
		printf("FNORD\n");
	}

VOIDLOOP:
	switch(varType){
		case kNPint:
			printf("kNPint param : %d\n", param);
			npNodeGetInt(nodeID, param, &val, data);
			printf("after npNodeGetInt\n");
			obj = Py_BuildValue("i", val);
			printf("after Py_BuildValue\n");
			break;
		case kNPintXYZ:
			printf("kNPintXYZ param : %d\n", param);
			npNodeGetIntXYZ(nodeID, param, &val, &(int)fVal, &(int)fValY, data);
			obj = Py_BuildValue("iii", val, fVal, fValY);
			break;
		case kNPfloat:
			printf("kNPfloat param : %d\n", param);
			npNodeGetFloat(nodeID, param, &fVal, data);
			obj = Py_BuildValue("f", fVal);
			break;
		case kNPfloatXYZ:
			printf("kNPfloatXYZ\n");
			npNodeGetFloatXYZ(nodeID, param, &fVal, &fValY, &fValZ, data);
			printf("xyz : %3f, %3f, %3f\n", fVal, fValY, fValZ);
			obj = Py_BuildValue("fff", fVal, fValY, fValZ);
			break;
		case kNPubyteRGBA:
			printf("kNPubyteRGBA\n");
			npNodeGetUbyteRGBA(nodeID, param, &r, &g, &b, &a, data);
			printf("ubyteRGBA : %c , %c , %c , %c\n", r,g,b,a);
			obj = Py_BuildValue("cccc", r,g,b,a); 
			break;
		case kNPbool:
			printf("kNPbool\n");
			npNodeGetBool(nodeID, param, &bo, data);
			printf("%d", bo);
			obj = Py_BuildValue("i", bo);
			break;
		case kNPvoidPtr:
			printf("kNPvoidPtr\n");
			printf("param : %d\n", param);
			if(param == kNPparent)
			{
				varType = kNPint;
				goto VOIDLOOP;
			}

			if(param == kNPchild)
			{
				varType = kNPint;
				goto VOIDLOOP;
			}
			break;
		default:
			printf("Unknown varType\n");
			Py_RETURN_NONE;
	}

	return obj;
}


static PyObject* np_PyCtrlCmd(PyObject *self, PyObject *args)
{
	void* data = npGetDataRef();
	if(!PyArg_ParseTuple(args, "i", &numargs))
		return NULL;

	printf("888 NUMARGS : %d\n", numargs);
	npCtrlCommand(numargs, data);
//	if(!PyArg_ParseTuple(args, ":PyCtrlCmd"))
//		return NULL;

	return Py_BuildValue("i", numargs);
}

static PyObject*
np_PyNodeNew(PyObject *self, PyObject *args)
{ 
	pNPnode node = NULL;
	pNPnode parentNode = NULL;
	int nodeType, parentId = 0;
	void* data = npGetDataRef();

	if(!PyArg_ParseTuple(args, "ii", &nodeType, &parentId))
		return NULL;

	parentNode = (pNPnode)npGetNodeByID(parentId, data);
	node = npNodeNew(nodeType, parentNode, data);

	//						 type(int), type(int)
	// nodeId = np.PyNodeNew(kNPpin,   nodeParentId);
	//npNodeNew(nodeType, nodeParent, dataRef);
//	system("pause");
	return Py_BuildValue("i", node->id);
}

static PyObject*
np_PyNodeDelete(PyObject *self, PyObject *args)
{
	pNPnode node = NULL;
	int nodeId = 0;
	void* data = npGetDataRef();

	printf("np_PyNodeDelete\n");
	if(!PyArg_ParseTuple(args, "i", &nodeId))
		return NULL;

	node = (pNPnode)npGetNodeByID(nodeId, data);
	npNodeDelete(node, data);

	Py_RETURN_NONE;
}

static PyObject*
np_PyNodeGetColor(PyObject *self, PyObject *args)
{
	PyObject* nodeColor = NULL;
	pNPnode node = NULL;
	int nodeId = 0;
	void* data = npGetDataRef();

	printf("np_PyNodeGetColor\n");
	if(!PyArg_ParseTuple(args, "i", &nodeId))
		return NULL;

	node = (pNPnode)npGetNodeByID(nodeId, data);
	nodeColor = Py_BuildValue("BBBB", node->color.r, node->color.g, node->color.b, node->color.a);
	//printf("0023 %u\n", node->color.r);
	//node->color.r (unsigned char)

	return nodeColor;
}

static PyObject*
np_PyNodeSetColor(PyObject *self, PyObject *args)
{
	PyObject* nodeColor = NULL;
	pNPnode node = NULL;
	unsigned char r,g,b,a = 0;
	int nodeId = 0;
	void* data = npGetDataRef();

	printf("np_PyNodeSetColor\n");
							 //id,r,g,b,a
	if(!PyArg_ParseTuple(args, "ibbbb", &nodeId, &r,&g,&b,&a))
		return NULL;

	node = (pNPnode)npGetNodeByID(nodeId, data);
	node->color.r = r; node->color.g = g; node->color.b = b; node->color.a = a;

	Py_RETURN_NONE;
}

static PyObject*
np_PyNodeCurrent(PyObject *self, PyObject *args)
{
	pData data = (pData)npGetDataRef();
	return Py_BuildValue("i", data->map.currentNode->id);
}

// Returns a list with all sibling ids
static PyObject*
np_PyNodeSelectAllSiblings(PyObject *self, PyObject *args)
{
	pData data = (pData)npGetDataRef();
	pNPnode node = NULL;
	pNPnode parentNode = NULL;
	PyObject* pyList = NULL;
	PyObject* pyID = NULL;
	int nodeId = 0;
	int childID[100] = {0};
	int childIDcount = 0;
	int i = 0;

	printf("np_PyNodeSelectAllSiblings\n");
	if(!PyArg_ParseTuple(args, "i", &nodeId))
		return NULL;

	node = (pNPnode)npGetNodeByID(nodeId, data);
//	node = data->map.currentNode;
	if(node->parent)
	{
		parentNode = node->parent;
		printf("Sibling Count : %d\n", parentNode->childCount);
		pyList = PyList_New(parentNode->childCount);
		for(i = 0; i < parentNode->childCount; i++)
		{
			parentNode->child[i]->selected = true;
			pyID = Py_BuildValue("i", parentNode->child[i]->id);
//			childIDcount++;
		//	childID[childIDcount] = parentNode->child[i]->id;
			PyList_SetItem(pyList, i, pyID);
		}
	}

	
	//node->
	//Py_RETURN_NONE;
	return pyList;
}

// subsample branch level ( np.PyNodeSubsampleBranchLevel(nodeID, sample(1,2,4,8,...) )
static PyObject*
np_PyNodeSubsampleBranchLevel(PyObject *self, PyObject *args)
{
	pData data = (pData)npGetDataRef();
	pNPnode node = NULL;
	pNPnode nodeParent = NULL;
//	int nodeId, branchLevel, sample, i = 0;
	int nodeId, sample, i = 0;

	if(!PyArg_ParseTuple(args, "ii", &nodeId, &sample))
		return NULL;

	node = (pNPnode)npGetNodeByID(nodeId, data);
	if(node)
	{
		if(node->parent)
		{
			nodeParent = node->parent;
			for(i = 0; i < node->parent->childCount; i++)
			{
				printf("i : %d\n", i+1);
				printf("ss : %d\n", ((i+1) % sample));
				if( ((i+1) % sample) == 0)
				{	
					nodeParent->child[i]->hide = !nodeParent->child[i]->hide;
				}
			}
		}
	}
	Py_RETURN_NONE;
}

static PyMethodDef npMethods[] = {
	{"PyCtrlCmd", np_PyCtrlCmd, METH_VARARGS,
	"npCtrlCommand"},
	{"PyNodeNew", np_PyNodeNew, METH_VARARGS, 
	"npNodeNew"},
	{"PyNodeDelete", np_PyNodeDelete, METH_VARARGS,
	"npNodeDelete"},
	{"PyNodeGetColor", np_PyNodeGetColor, METH_VARARGS,
	"npNodeGetColor"},
	{"PyNodeSetColor", np_PyNodeSetColor, METH_VARARGS,
	"npNodeSetColor"},
	{"PyNodeCurrent", np_PyNodeCurrent, METH_VARARGS,
	"npNodeCurrent"},
	{"PyNodeSelectAllSiblings", np_PyNodeSelectAllSiblings, METH_VARARGS,
	"npNodeSelectAllSiblings"},
	{"PyNodeSubsampleBranchLevel", np_PyNodeSubsampleBranchLevel, METH_VARARGS,
	"npNodeSubsampleBranchLevel"},
	{"PyNodeGet", np_PyNodeGet, METH_VARARGS,
	"npNodeGet"},
	{"PyNodeSet", np_PyNodeSet, METH_VARARGS,
	"npNodeSet"},
	{"PyCurlGetURL", np_PyCurlGetURL, METH_VARARGS,
	"npCurlGetURL"},
	{"PyCurlGetRawResult", np_PyCurlGetRawResult, METH_VARARGS,
	"npCurlGetRawResult"},
	{"PyTagNodeWith", np_PyTagNodeWith, METH_VARARGS,
	"npPyTagNodeWith"},
	{"PyBuildAntzDict",  np_PyBuildAntzDict, METH_VARARGS,
	"npPyBuildAntzDict"},
	{NULL, NULL, 0, NULL} // Sentinel
};

//static PyObject* np_PyTagNodeWith(PyObject *self, PyObject *args)
//static PyObject* np_PyCurlGetRawResult(PyObject *self, PyObject *args)
//static PyObject* np_PyCurlGetURL(PyObject *self, PyObject *args)
//static PyObject* np_PyNodeSet(PyObject *self, PyObject *args)

void npPyTest2(void* dataRef)
{
	pData data = (pData) dataRef;
	char filePath[256] = "antz.py";
	FILE* fp = NULL;
	
	//sprintf(filePath, "%santz.py", data->io.file.appPath);
	fp = npFileOpen(filePath, "r", dataRef);
	PyRun_SimpleFile(fp, "antz.py");
	npFileClose(fp, dataRef);
//	system("pause");
}

void npPyFun1(void* dataRef)
{
	pData data = (pData) dataRef;
//	PyObject *pName, *pDict, *pFunc;
  //  PyObject *pArgs, *pValue;
//	PyObject* pFunc, pValue;
	PyObject *pFunc;
	PyObject *pValue;

	printf("1 pModule ptr : %p\n", pModule);
	//pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
	{
		//pModule = PyImport_Import(pName);
		pModule = PyImport_ImportModule("antz-plugin-ex");
	}
	else
		pModule = PyImport_ReloadModule(pModule);
	
	if(pModule == NULL)
		return;

	printf("1 pModule ptr : %p\n", pModule);
	//Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun1");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun2(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
//	PyObject *pName, *pDict, *pFunc;
//   PyObject *pArgs, *pValue;
	PyObject *pName;
	PyObject *pFunc;
	PyObject *pValue;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	if(pModule == NULL)
		return;

	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun2");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun3(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
	PyObject *pName, *pFunc;
    PyObject *pValue;
	PyObject *exception;

//	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
	{
		pModule = PyImport_ImportModule("antz-plugin-ex");
		exception = PyErr_Occurred();
		if(exception)
		{
			printf("Caught exception\n");
		}
	}
	else
	{
		pModule = PyImport_ReloadModule(pModule);
	}
	
	if(pModule)
	{
//		Py_DECREF(pName);
		pFunc = PyObject_GetAttrString(pModule, "npFun3");
		pValue = PyObject_CallObject(pFunc, NULL);
		Py_DECREF(pFunc);
	}
	else
	{
		printf("cannot load module\n");
		PyErr_Print();
	}
   // Py_DECREF(pModule);
}

void npPyFun4(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
	PyObject *pName, *pFunc;
    PyObject *pValue;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun4");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun5(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
	PyObject *pName, *pFunc;
    PyObject *pValue;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun5");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun6(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
	PyObject *pName, *pFunc;
    PyObject *pValue;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun6");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun7(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
//	PyObject *pName, *pDict, *pFunc;
  //  PyObject *pArgs, *pValue;
	PyObject *pFunc, *pValue, *pName;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun7");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun8(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
	PyObject *pName, *pFunc;
    PyObject *pValue;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun8");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun9(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
	PyObject *pName, *pFunc;
    PyObject *pValue;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun9");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun0(void* dataRef)
{
	pData data = (pData) dataRef;
	static PyObject *pModule = NULL;
	PyObject *pName, *pFunc;
    PyObject *pValue;

	pName = PyString_FromString("antz-plugin-ex");
	if(pModule == NULL)
		pModule = PyImport_Import(pName);
	else
		pModule = PyImport_ReloadModule(pModule);
	
	Py_DECREF(pName);
	pFunc = PyObject_GetAttrString(pModule, "npFun0");
	pValue = PyObject_CallObject(pFunc, NULL);
	Py_DECREF(pFunc);
   // Py_DECREF(pModule);
}

void npPyFun(int key, void* dataRef)
{
	switch(key)
	{
		case 1:
			printf("npPyFun1\n");
			npPyFun1(dataRef);
			break;
		case 2:
			printf("npPyFun2\n");
			npPyFun2(dataRef);
			break;
		case 3:
			printf("npPyFun3\n");
			npPyFun3(dataRef);
			break;
		case 4:
			printf("npPyFun4\n");
			npPyFun4(dataRef);
			break;
		case 5:
			printf("npPyFun5\n");
			npPyFun5(dataRef);
			break;
		case 6:
			printf("npPyFun6\n");
			npPyFun6(dataRef);
			break;
		case 7:
			printf("npPyFun7\n");
			npPyFun7(dataRef);
			break;
		case 8:
			printf("npPyFun8\n");
			npPyFun8(dataRef);
			break;
		case 9:
			printf("npPyFun9\n");
			npPyFun9(dataRef);
			break;
		case 0:
			printf("npPyFun0\n");
			npPyFun0(dataRef);
			break;
	}
}
/*
void npPyTest(void* dataRef)
{
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue, *pInt, *pArgA, *pArgB;
    int i;

    if (1 == 0) {
        fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
  //      return 1;
    }

	printf("Before Py_init\n");
    Py_Initialize();
	printf("After Py_init : %s\n", Py_GetPath());

	pArgA = PyInt_FromLong(9);
	pArgB = PyInt_FromLong(3);
	pArgs = PyTuple_New(2);

	PyTuple_SetItem(pArgs, 0, pArgA);
	PyTuple_SetItem(pArgs, 1, pArgB);

    pName = PyString_FromString("np");
	pModule = PyImport_Import(pName);
	pDict = PyModule_GetDict(pModule);

	pFunc = PyDict_GetItemString(pDict, "multiply");
//	pInt = PyInt_FromLong(5);


	if(PyCallable_Check(pFunc))
		pValue = PyObject_CallObject(pFunc, pArgs);
	else
		PyErr_Print();

	printf("pValue : %d\n", PyInt_AsLong(pValue));
	Py_DECREF(pModule);	 
	Py_DECREF(pName);

	Py_Finalize();

	return;
}
*/
//------------------------------------------------------------------------------
void npPyUpdate (void* dataRef)							//add to ctrl loop, debug zz
{
	return;
}

//------------------------------------------------------------------------------

void npInitPy(void* dataRef)
{
	pData data = (pData)dataRef;
	char pyPath[1024] = {'\0'};
	printf("data->io.file.appPath : %s\n", data->io.file.appPath);
	sprintf(pyPath, "%ssdk\\libs\\python", data->io.file.appPath);
	printf("pyPath : %s\n", pyPath);
	//Py_SetProgramName(pyPath);
	Py_SetPythonHome(pyPath);
	Py_Initialize();
	printf("after Py_init\n");
	//npNodeMapIDtoType(kNPbranchLevel, dataRef);
	Py_InitModule("np", npMethods);
	//npPyBuildAntzDictionary(dataRef);
}