#include <cave_ogl.h>
#include <GL/glu.h>
#include <string.h>
#include <sys/stat.h>
#include <python2.2/Python.h>


void init_gl(void);
void draw(void);
void update(void);
void loadScript(void);
static void initializePython(void);

char *filename;
time_t lastModified=0;

main(int argc,char **argv)
    {
    CAVEConfigure(&argc,argv,NULL);
    if (argc < 2)
        {
        fprintf(stderr,"Usage: %s script.py\n",argv[0]);
        exit(1);
        }
    filename = strdup(argv[1]);
    CAVEInit();
    CAVEInitApplication(init_gl,0);
    CAVEFrameFunction(update,0);
    CAVEDisplay(draw,0);
    while (!CAVEgetbutton(CAVE_ESCKEY))
	    {
    	usleep(10000);
	    }
    Py_Finalize();
    CAVEExit();
    }


void init_gl(void)
    {
    initializePython();
    loadScript();
    }

void loadScript(void)
    {
    FILE *fp;
    struct stat info;
    PyRun_SimpleString("def draw(): pass\n");
    PyRun_SimpleString("def update(): pass\n");
    fp = fopen(filename, "r");
    if (!fp)
        {
        perror(filename);
        exit(1);
        }
    PyRun_SimpleFile(fp, filename);
    fclose(fp);
    if (stat(filename, &info) != -1)
        lastModified = info.st_mtime;
    }


void update(void)
    {
    struct stat info;
    if (stat(filename, &info) != -1)
        {
        if (lastModified != info.st_mtime)
            loadScript();
        }
    PyRun_SimpleString("update()\n");
    }


void draw(void)
    {
    PyRun_SimpleString("draw()\n");
    }



static PyObject* emb_getPosition(PyObject *self, PyObject *args)
	{
    int target;
    float retval[3] = {0,0,0};
	if (!PyArg_ParseTuple(args, "i", &target))
        	return NULL;
    CAVEGetPosition(target, retval);
	return Py_BuildValue("[f,f,f]", retval[0], retval[1], retval[2]);
	}



static PyObject* emb_getOrientation(PyObject *self, PyObject *args)
	{
    int target;
    float retval[3] = {0,0,0};
	if (!PyArg_ParseTuple(args, "i", &target))
        	return NULL;
    CAVEGetOrientation(target, retval);
	return Py_BuildValue("[f,f,f]", retval[0], retval[1], retval[2]);
	}


static PyObject* emb_getVector(PyObject *self, PyObject *args)
	{
    int target;
    float retval[3] = {0,0,0};
	if (!PyArg_ParseTuple(args, "i", &target))
        	return NULL;
    CAVEGetVector(target, retval);
	return Py_BuildValue("[f,f,f]", retval[0], retval[1], retval[2]);
	}


static PyObject* emb_getWandButtons(PyObject *self, PyObject *args)
	{
	if (!PyArg_ParseTuple(args, ""))
        	return NULL;
	return Py_BuildValue("[i,i,i]", CAVEBUTTON1, CAVEBUTTON2, CAVEBUTTON3);
	}


static PyObject* emb_getWandJoystick(PyObject *self, PyObject *args)
	{
	if (!PyArg_ParseTuple(args, ""))
        	return NULL;
	return Py_BuildValue("[f,f]", CAVE_JOYSTICK_X, CAVE_JOYSTICK_Y);
	}


static PyMethodDef EmbMethods[] =
	{
	{"CAVEGetPosition", emb_getPosition, METH_VARARGS,
		"Returns position of a CAVE tracker."},
	{"CAVEGetOrientation", emb_getOrientation, METH_VARARGS,
		"Returns orientation of a CAVE tracker."},
	{"CAVEGetVector", emb_getVector, METH_VARARGS,
		"Returns direction vector (front/back/etc) of a CAVE tracker."},
	{"CAVEGetWandButtons", emb_getWandButtons, METH_VARARGS,
		"Returns state of wand buttons."},
	{"CAVEGetWandJoystick", emb_getWandJoystick, METH_VARARGS,
		"Returns state of wand joystick."},
	{NULL, NULL, 0, NULL}
	};

static struct {char *name; int value;} caveConstants[] =
    {
    { "CAVE_HEAD", CAVE_HEAD },
    { "CAVE_WAND", CAVE_WAND },
    { "CAVE_LEFT_EYE", CAVE_LEFT_EYE },
    { "CAVE_RIGHT_EYE", CAVE_RIGHT_EYE },
    { "CAVE_HEAD_NAV", CAVE_HEAD_NAV },
    { "CAVE_WAND_NAV", CAVE_WAND_NAV },
    { "CAVE_LEFT_EYE_NAV", CAVE_LEFT_EYE_NAV },
    { "CAVE_RIGHT_EYE_NAV", CAVE_RIGHT_EYE_NAV },
    { "CAVE_HEAD_FRONT", CAVE_HEAD_FRONT },
    { "CAVE_HEAD_BACK", CAVE_HEAD_BACK },
    { "CAVE_HEAD_LEFT", CAVE_HEAD_LEFT },
    { "CAVE_HEAD_RIGHT", CAVE_HEAD_RIGHT },
    { "CAVE_HEAD_UP", CAVE_HEAD_UP },
    { "CAVE_HEAD_DOWN", CAVE_HEAD_DOWN },
    { "CAVE_WAND_FRONT", CAVE_WAND_FRONT },
    { "CAVE_WAND_BACK", CAVE_WAND_BACK },
    { "CAVE_WAND_LEFT", CAVE_WAND_LEFT },
    { "CAVE_WAND_RIGHT", CAVE_WAND_RIGHT },
    { "CAVE_WAND_UP", CAVE_WAND_UP },
    { "CAVE_WAND_DOWN", CAVE_WAND_DOWN },
    { NULL, 0 }
    };

static void initializePython(void)
    {
    char str[512];
    int i;
    char *path = getenv("PYTHONPATH"), *newpath;
    if (path)
        {
        newpath = malloc(strlen(path)+14);
        sprintf(newpath, "PYTHONPATH=%s:.",path);
        }
    else
        newpath = strdup("PYTHONPATH=.");
    putenv(newpath);

    Py_Initialize();
	Py_InitModule("cave", EmbMethods);
    for (i=0; caveConstants[i].name; i++)
        {
        sprintf(str, "%s = %d\n", caveConstants[i].name, caveConstants[i].value);
        PyRun_SimpleString(str);
        }
    }
