#ifndef __PYTHON_THREADS_H
#define __PYTHON_THREADS_H

#include <Python.h>

#if defined(WIN32)
#include <windows.h>
#endif // WIN32 && !NDEBUG

#include <list>

class PythonThread;

class PythonDebugListener {
public:
	virtual void entryFunction(const char *name) = 0;
	virtual void exitFunction(const char *name) = 0;
};

typedef std::list<PyThreadState*> ThreadStateList;

class PythonMgr {
	friend class PythonMgrCreator;
	
public:
	typedef enum {
		_py_print_errors = 0,
		_py_print_all = 5
	} PythonUtilsDebugLevel;

	static PythonMgr *instance();

	PyThreadState *createThreadInfo();

	void destroyThreadInfo(PyThreadState *info);

	void destroyAllThreadInfos();

	void swap(PythonThread *thread = NULL);

	void setDebugLevel(PythonUtilsDebugLevel debugLevel) { _debugLevel = (int) debugLevel; }

	void setListener(PythonDebugListener *list) { _listener = list; }
	PythonDebugListener *listener() { return _listener; }

	PythonUtilsDebugLevel getDebugLevel() { return (PythonUtilsDebugLevel) _debugLevel; }

protected:
	PythonMgr();
	~PythonMgr();

	static void destroy();
private:
	static PythonMgr *_instance;
	PyThreadState *_mainThreadState;
	bool _init;
	int _debugLevel;
	PythonDebugListener *_listener;
	ThreadStateList _threadInfos;
};


/**
This class must be created when a thread is created in C++ and python code is called from this thread.<br>
Interpreter is locked until the instance of the class is deleted.
*/
class PythonThread {
public:
	PythonThread();
	~PythonThread();

	PyThreadState *threadState() { return _threadInfo; }
	
private:
	PyThreadState *_threadInfo;
};


class PythonArgs {
public:
	static PyObject *createArg(int argc, char **argv);
	static PyObject *createArg(const char *arg);
};

class PythonAutoLock {
public:
	PythonAutoLock(const char *name = NULL);
	~PythonAutoLock();

private:
	const char *_name;
	PyThreadState *_state;
};

#define ENTER_FUNCTION(x) PythonAutoLock pyInterpreterLock(#x);



#endif // __PYTHON_THREADS_H