/* --------------------------------------------------------------------------
 *	ScriptEngine
 * --------------------------------------------------------------------------
 *	
 *	Embedded Python Script Engine
 *
 * --------------------------------------------------------------------------
 *	
 *	prog:	max rheiner / max.rheiner@zhdk.ch
 *	date:	9/2/2007	(m/d/y)
 *
 * ----------------------------------------------------------------------------
 */

#include "ScriptEngine.hxx"

#include <iostream>
#include <string>
#include <sstream>

using namespace scriptEngine;
using namespace boost::python;

///////////////////////////////////////////////////////////////////////////////
// globals
PyObject* _mainDict;

PyObject* scriptEngine::GetMainDict()
{
	return _mainDict;
}


///////////////////////////////////////////////////////////////////////////////
// functions

void scriptEngine::Start()
{
	// init python
	Py_Initialize();

	// setup the environment
	PyRun_SimpleString(
	"import sys\n"
	//"import os\n"
	);

	// add working dir
	PyRun_SimpleString("sys.path.insert(0,'./')");

	PyObject* mainModule	= PyImport_AddModule("__main__");
	_mainDict = PyModule_GetDict(mainModule);

}

void scriptEngine::End()
{
	// ends python
	Py_Finalize();
}

void scriptEngine::Run(const std::string& code)
{
	PyRun_SimpleString(code.c_str());
}

bool scriptEngine::Load(const std::string& file)
{
	FILE* fp=fopen (file.c_str(),"r");
	if(fp)
	{
		PyRun_SimpleFile(fp,file.c_str());
		
		fclose(fp);
		return true;
	}
	else
		return false;
}

int readInt(PyObject* obj,int defValue=0)
{
	if(obj == NULL)
		return defValue;
	else if(PyInt_Check(obj))
		return PyInt_AS_LONG(obj);
	else if(PyFloat_Check(obj))
		return (int)PyFloat_AS_DOUBLE(obj);
	else
		return defValue;
}

float scriptEngine::readFloat(PyObject* obj,float defValue)
{
	if(obj == NULL)
		return defValue;
	else if(PyFloat_Check(obj) )
		return PyFloat_AS_DOUBLE(obj);
	else if(PyInt_Check(obj))
		return (float)PyInt_AS_LONG(obj);
	else
		return defValue;
}

std::string readStr(PyObject* obj,const std::string& defValue="")
{
	if(obj == NULL)
		return defValue;
	else if(PyString_Check(obj) )
		return PyString_AS_STRING(obj);
	else if(PyInt_Check(obj))
	{
		std::ostringstream os;
		os << PyInt_AS_LONG(obj);
		return os.str();
	}
	else if(PyFloat_Check(obj))
	{
		std::ostringstream os;
		os << PyFloat_AS_DOUBLE(obj);
		return os.str();
	}
	else
		return defValue;
}

int scriptEngine::GetIntValue(const std::string& varName,int defaultValue)
{
	PyObject* item = PyDict_GetItemString(_mainDict,varName.c_str());
	return readInt(item,defaultValue);
}

float scriptEngine::GetFloatValue(const std::string& varName,float defaultValue)
{
	PyObject* item = PyDict_GetItemString(_mainDict,varName.c_str());
	return readFloat(item,defaultValue);
}

std::string scriptEngine::GetStrValue(const std::string& varName,const std::string& defaultValue)
{
	PyObject* item = PyDict_GetItemString(_mainDict,varName.c_str());
	return readStr(item,defaultValue);
}

int scriptEngine::GetIntArray(const std::string& varName,IntList& list,bool clearArray)
{
	if(clearArray)
		list.clear();

	PyObject* item = PyDict_GetItemString(_mainDict,varName.c_str());
	if(item==NULL)
		return list.size();
	
	// check if this var is an iteratorable object
	PyObject *itr = PyObject_GetIter(item);
	if(PyErr_Occurred())
		return list.size();

	PyObject *itemItr=NULL;
	while (itemItr = PyIter_Next(itr)) 
		list.push_back(readInt(itemItr));

	return list.size();
}

int scriptEngine::GetFloatArray(const std::string& varName,FloatList& list,bool clearArray)
{
	if(clearArray)
		list.clear();

	PyObject* item = PyDict_GetItemString(_mainDict,varName.c_str());
	if(item==NULL)
		return list.size();
	
	// check if this var is an iteratorable object
	PyObject *itr = PyObject_GetIter(item);
	if(PyErr_Occurred())
		return list.size();

	PyObject *itemItr=NULL;
	while (itemItr = PyIter_Next(itr)) 
		list.push_back(readFloat(itemItr));

	return list.size();
}


int scriptEngine::GetStrArray(const std::string& varName,StringList& list,bool clearArray)
{
	if(clearArray)
		list.clear();

	PyObject* item = PyDict_GetItemString(_mainDict,varName.c_str());
	if(item==NULL)
		return list.size();
	
	// check if this var is an iteratorable object
	PyObject *itr = PyObject_GetIter(item);
	if(PyErr_Occurred())
		return list.size();

	PyObject *itemItr=NULL;
	while (itemItr = PyIter_Next(itr)) 
		list.push_back(readStr(itemItr));

	return list.size();
}

std::string 
scriptEngine::GetStrDict(const std::string& varName,const std::string& key,const std::string& defaultValue)
{
	std::string ret=defaultValue;

	PyObject* item = PyDict_GetItemString(_mainDict,varName.c_str());
	if(item==NULL)
		return ret;
	
	// check if this var dict
	if(	PyDict_Check(item) == 0)
		return ret;

	PyObject *value=PyDict_GetItemString(item,key.c_str());
	if(value)
		ret=readStr(value);

	return ret;
}



