/* -*- Mode: C; c-basic-offset: 4 -*- */
%%
headers
#include <Python.h>

#include "mateconf-fixes.h"
#include "mateconf-types.h"

#define NO_IMPORT_PYGOBJECT
#include "pygobject.h"
#include <glib.h>
#include <mateconf/mateconf-client.h>
#include <mateconf/mateconf-enum-types.h>
#include "config.h"

static gpointer pymateconf_parse_pygvalue(MateConfValueType gvalue_type,
				       PyObject *pyvalue);
%%
modulename mateconf
%%
import gobject.GObject as PyGObject_Type
%%
ignore-glob
 _*
 mateconf_*init
%%
ignore
  mateconf_change_set_get_type
  mateconf_client_get_type
  mateconf_value_type_get_type
  mateconf_error_get_type
  mateconf_client_preload_type_get_type
  mateconf_client_error_handling_mode_get_type
  mateconf_value_set_car_nocopy
  mateconf_value_set_cdr_nocopy
  mateconf_client_change_set_from_currentv
  mateconf_value_set_list_nocopy

%%
override-slot MateConfClient.tp_init

static int
_wrap_mateconf_client_tp_init(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { NULL };

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":mateconf.Client.__init__", kwlist)) {
        return -1;
    }
    self->obj = (GObject *) mateconf_client_get_default();
    pygobject_register_wrapper((PyObject *)self);
    return 0;
}

%%
override mateconf_client_notify_add kwargs
void
pymateconf_client_notify_add(MateConfClient *client,
			  guint        cnxn_id,
			  MateConfEntry  *entry,
			  gpointer     user_data)
{
 	PyObject *func;
	PyObject *userdata = NULL;
	PyObject *ret;
	PyObject *tuple = (PyObject*)user_data;
	PyGILState_STATE state;

        state = pyg_gil_state_ensure();

	g_assert(PyTuple_Check(tuple));
        func = PyTuple_GetItem(tuple, 0);
        userdata = PyTuple_GetItem(tuple, 1);

	if (!userdata) {
		ret = PyObject_CallFunction(func, "NNN",
					    pygobject_new((GObject *)client),
					    PyLong_FromUnsignedLong(cnxn_id),
					    pyg_boxed_new(MATECONF_TYPE_ENTRY,
							  entry,
							  TRUE, TRUE));
	} else {
		ret = PyObject_CallFunction(func, "NNNO",
					    pygobject_new((GObject *)client),
					    PyLong_FromUnsignedLong(cnxn_id),
					    pyg_boxed_new(MATECONF_TYPE_ENTRY,
							  entry,
							  TRUE, TRUE),
					    userdata);		
	}
	
	if (ret == NULL)
            PyErr_Print();
	else
            Py_DECREF(ret);

	pyg_gil_state_release(state);
}
			  
static PyObject *
_wrap_mateconf_client_notify_add(PyGObject *self, PyObject *args,
			      PyObject *kwargs)
{
	static char *kwlist[] = { "namespace_section", "func",
				  "user_data", NULL };
	gchar *namespace_section;
	PyObject *callback;
	PyObject *extra = NULL;
	PyObject *data;
	guint retval;
	
	if (!PyArg_ParseTupleAndKeywords(args, kwargs,
					 "sO|O:MateConfClient.notify_ad",
					 kwlist, &namespace_section,
					 &callback, &extra)) {
		return NULL;
	}
	
	if (!PyCallable_Check(callback)) {
		PyErr_SetString(PyExc_TypeError, "second arg not callable");
		return NULL;
	}
	
	if (extra) {
		Py_INCREF(extra);
	} else {
		extra = PyTuple_New(0);
	}
	
	data = Py_BuildValue("(ON)", callback, extra);
	
	retval = mateconf_client_notify_add(MATECONF_CLIENT(self->obj),
					 namespace_section,
					 pymateconf_client_notify_add,
					 data,
					 (GFreeFunc)pyg_destroy_notify,
					 NULL);
	
	return PyLong_FromUnsignedLong((unsigned long) retval);
}

%%
override mateconf_client_all_entries args
static PyObject *
_wrap_mateconf_client_all_entries(PyGObject *self, PyObject *args)
{
	gchar *path;
	GError *err = NULL;
	GSList *values;
	GSList *list;
	PyObject *pylist;
	int i = 0;
	
	if (!PyArg_ParseTuple(args, "s:MateConfClient.all_entries", &path)) {
		return NULL;
	}
	    
	values = mateconf_client_all_entries(MATECONF_CLIENT(self->obj), path, &err);
	if (pyg_error_check(&err)) {
		return NULL;
	}
	    
	pylist = PyTuple_New(g_slist_length(values));
	for (list = values; list; list = list->next) {
		MateConfEntry *entry = list->data;
		PyObject *pyentry = pyg_boxed_new(MATECONF_TYPE_ENTRY, entry,
						  FALSE, TRUE);
		PyTuple_SetItem(pylist, i++, pyentry);
	}
	
	return pylist;
}

%%
override mateconf_client_all_dirs args
static PyObject *
_wrap_mateconf_client_all_dirs(PyGObject *self, PyObject *args)
{
	gchar *path;
	GError *err = NULL;
	GSList *values;
	GSList *list;
	PyObject *pylist;
	int i = 0;
	
	if (!PyArg_ParseTuple(args, "s:MateConfClient.all_dirs", &path)) {
		return NULL;
	}
	    
	values = mateconf_client_all_dirs(MATECONF_CLIENT(self->obj), path, &err);
	if (pyg_error_check(&err)) {
		return NULL;
	}
	    
	pylist = PyTuple_New(g_slist_length(values));
	for (list = values; list; list = list->next) {
		PyObject *pystring = PyString_FromString(list->data);

		PyTuple_SetItem(pylist, i++, pystring);
	}
	
	return pylist;
}

%%
override mateconf_client_get_pair kwargs
/* Return a proper PyObject for retloc based on its type. */
static PyObject *
pymateconf_parse_gvalue(MateConfValueType gvalue_type, gpointer retloc)
{
    PyObject *retval;
    switch(gvalue_type) {
	case MATECONF_VALUE_INT:
	case MATECONF_VALUE_BOOL:
	    retval = PyInt_FromLong(*(gint*)retloc);
	    break;
	case MATECONF_VALUE_FLOAT:
	    retval = PyFloat_FromDouble(*(gdouble*)retloc);
	    break;
	case MATECONF_VALUE_STRING:
        {
            gchar **s = (gchar **) retloc;
            if (*s)
                retval = PyString_FromString(*s);
            else {
                Py_INCREF(Py_None);
                return Py_None;
            }
	    break;
        }
	case MATECONF_VALUE_SCHEMA:
	    retval = pyg_boxed_new(MATECONF_TYPE_SCHEMA, *(MateConfSchema**)retloc, 
		    TRUE, TRUE);
	    break;
	default:
	    PyErr_SetString(PyExc_TypeError, "Unknown MateConfValueType.");
	    retval = NULL;
	    break;
    }
    return retval;
}

/* Get the value of a PyObject from its type. */
/* g_new0() on returned pointer, need to free it. */
static gpointer
pymateconf_parse_pygvalue(MateConfValueType gvalue_type, PyObject *pyvalue)
{
    gpointer retval;
    retval = g_new0(gpointer, 1);
    switch(gvalue_type) {
	case MATECONF_VALUE_INT:
	case MATECONF_VALUE_BOOL:
	    *(gint*)retval = (gint) PyInt_AsLong(pyvalue);
	    break;
	case MATECONF_VALUE_FLOAT:
	    *(gdouble*)retval = PyFloat_AsDouble(pyvalue);
	    break;
	case MATECONF_VALUE_STRING:
	    if (!PyString_Check(pyvalue)) {
		PyErr_SetString(PyExc_TypeError,
				"value should be a string");
		g_free(retval);
		return NULL;
	    }
	    *(gchar**)retval = PyString_AsString(pyvalue);
	    break;
	case MATECONF_VALUE_SCHEMA:
	    if (pyg_boxed_check(pyvalue, MATECONF_TYPE_SCHEMA)) {
		*(MateConfSchema**)retval = pyg_boxed_get(pyvalue, MateConfSchema);
	    } else {
		PyErr_SetString(PyExc_TypeError,
				"value should be a MateConfSchema");
		free(retval);
		retval = NULL;
	    }
	    break;
	default:
	    PyErr_SetString(PyExc_TypeError, "Unknown MateConfValueType.");
	    free(retval);
	    retval = NULL;
	    break;
    }
    return retval;
}

static gpointer
pymateconf_new_type(MateConfValueType t)
{
    gpointer retval;
    switch(t) {
	case MATECONF_VALUE_INT:
	case MATECONF_VALUE_BOOL:
	    retval = g_new0(gint, 1);
	    break;
	case MATECONF_VALUE_FLOAT:
	    retval = g_new0(gdouble, 1);
	    break;
	case MATECONF_VALUE_STRING:
	    retval = g_new0(gchar, 1);
	    break;
	case MATECONF_VALUE_SCHEMA:
	    retval = mateconf_schema_new(); 
	    break;
	default:
	    PyErr_SetString(PyExc_TypeError, "Unknown MateConfValueType.");
	    retval = NULL;
	    break;
    }
    return retval;
}

static PyObject *
_wrap_mateconf_client_get_pair(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "key", "car_type", "cdr_type", NULL };
    char *key;
    PyObject *pycar_type = NULL, *pycdr_type = NULL;
    PyObject *retcar = NULL, *retcdr = NULL;
    MateConfValueType car_type, cdr_type;
    gpointer car_retloc = NULL;
    gpointer cdr_retloc = NULL;
    int ret;

    GError *err = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOO:MateConfClient.get_pair",
		kwlist, &key, &pycar_type, &pycdr_type))
	return NULL;

    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE,
			   pycar_type, (gint *)&car_type))
	return NULL;
    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE,
			   pycdr_type, (gint *)&cdr_type))
	return NULL;
    
    car_retloc = pymateconf_new_type(car_type);
    if (!car_retloc) 
	return NULL;
    cdr_retloc = pymateconf_new_type(cdr_type);
    if (!cdr_retloc) {
	if(car_type == MATECONF_VALUE_SCHEMA)
	    mateconf_schema_free(car_retloc);
	else 
	    g_free(car_retloc);
	return NULL;
    }
	    
    ret = mateconf_client_get_pair(MATECONF_CLIENT(self->obj), key, car_type, 
	    cdr_type, car_retloc, cdr_retloc, &err);
    if (pyg_error_check(&err))
	return NULL;
    retcar = pymateconf_parse_gvalue(car_type, car_retloc);
    retcdr = pymateconf_parse_gvalue(cdr_type, cdr_retloc);

    if (car_type != MATECONF_VALUE_SCHEMA)
	g_free(car_retloc);
    /* FIXME: mateconf_schema_free(car_retloc)? */
    else
	mateconf_schema_free(car_retloc);

    if (cdr_type != MATECONF_VALUE_SCHEMA)
	g_free(cdr_retloc);
    else
	mateconf_schema_free(cdr_retloc);

    if (!retcar || !retcdr)
	return NULL;
    return Py_BuildValue("(NN)", retcar, retcdr);
}

%%
override mateconf_client_set_pair kwargs
static PyObject *
_wrap_mateconf_client_set_pair(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "key", "car_type", "cdr_type",
			      "car", "cdr",  NULL };
    char *key;
    PyObject *pycar_type = NULL, *pycdr_type = NULL;
    PyObject *pycar = NULL, *pycdr = NULL;

    MateConfValueType car_type, cdr_type;
    gpointer car, cdr;
    int ret;
    GError *err = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
				     "sOOOO:MateConfClient.set_pair",
				     kwlist, &key, &pycar_type, &pycdr_type,
				     &pycar, &pycdr))
	return NULL;

    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE,
			   pycar_type, (gint *)&car_type))
	return NULL;
    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE,
			   pycdr_type, (gint *)&cdr_type))
	return NULL;
    car = pymateconf_parse_pygvalue(car_type, pycar);
    if (!car) 
    	return NULL;
    cdr = pymateconf_parse_pygvalue(cdr_type, pycdr);
    if (!cdr) {
	g_free(car);
	return NULL;
    }
	

    ret = mateconf_client_set_pair(MATECONF_CLIENT(self->obj),
				key, car_type, cdr_type,
				car, cdr, &err);

    g_free(car);
    g_free(cdr);

    if (pyg_error_check(&err))
	return NULL;
    return PyInt_FromLong(ret);
}

%%
override mateconf_client_get_list kwargs
    static PyObject *
pymateconf_parse_listvalue(MateConfValueType gvalue_type, gpointer retloc)
{
    PyObject *retval;
    switch(gvalue_type) {
	case MATECONF_VALUE_INT:
	case MATECONF_VALUE_BOOL:
	    retval = PyInt_FromLong(GPOINTER_TO_INT(retloc));
	    break;
	case MATECONF_VALUE_FLOAT:
	    retval = PyFloat_FromDouble(*(gdouble*)retloc);
	    break;
	case MATECONF_VALUE_STRING:
	    retval = PyString_FromString((gchar*)retloc);
	    break;
	case MATECONF_VALUE_SCHEMA:
	    retval = pyg_boxed_new(MATECONF_TYPE_SCHEMA, (MateConfSchema*)retloc, 
		    TRUE, TRUE);
	    break;
	default:
	    /* Should not reach here. get_list should always valid. */
	    PyErr_SetString(PyExc_TypeError, "Unknown MateConfValueType.");
	    retval = NULL;
	    break;
    }
    return retval;
}

static PyObject *
_wrap_mateconf_client_get_list(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "key", "list_type", NULL };
    char *key;
    PyObject *py_type = NULL;
    PyObject *py_list = NULL;
    MateConfValueType lstype;
    GSList *retlist, *ilist;
    gpointer data;
    int lslen, i;

    GError *err = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO:MateConfClient.get_list",
		kwlist, &key, &py_type))
	return NULL;

    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE, py_type, (gint *)&lstype))
	return NULL;
    
    retlist = mateconf_client_get_list(MATECONF_CLIENT(self->obj), key,
				    lstype, &err);
    if (pyg_error_check(&err)) {
	return NULL;
    } else if (retlist == NULL) {
	return PyList_New(0);
    }
    
    lslen = g_slist_length(retlist);
    i = 0;
    py_list = PyList_New(lslen);
    for (ilist = retlist; ilist; ilist = ilist->next) {
	PyObject *py_data;
	data = ilist->data;
	py_data = pymateconf_parse_listvalue(lstype, data);
	if (!py_data) {
	    g_slist_free(retlist);
	    return NULL;
	}
	PyList_SetItem(py_list, i, py_data);
	i++;
	if (lstype == MATECONF_VALUE_SCHEMA)
	    mateconf_schema_free(data);
	else if(lstype == MATECONF_VALUE_FLOAT || lstype == MATECONF_VALUE_STRING)
	    g_free(data);
    }
    g_slist_free(retlist);
    return py_list;
}

%%
override mateconf_client_set_list kwargs
static PyObject *
_wrap_mateconf_client_set_list(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "key", "list_type", "list", NULL };
    char *key;
    PyObject *py_type = NULL;
    PyObject *py_list = NULL;
    GSList *clist = NULL;
    GSList *tmplist, *pointlist=NULL;
    MateConfValueType list_type;
    int ret, i;
    int retdata; /* Error flag. */
    GError *err = NULL;

    ret = 1;
    retdata = 1;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOO:MateConfClient.set_list",
		kwlist, &key, &py_type, &py_list))
	return NULL;
    if (!PyTuple_Check(py_list) && !PyList_Check(py_list)) {
	PyErr_SetString(PyExc_TypeError,
			"3rd argument should be a sequence type.");
	return NULL;
    }

    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE, py_type, (gint *)&list_type))
	return NULL;
    
    for (i = 0; i < PySequence_Size(py_list) && retdata; i++) {
	gpointer data;
	PyObject *item = PySequence_GetItem(py_list, i);
	data = pymateconf_parse_pygvalue(list_type, item);
	Py_XDECREF(item);
	if (data == NULL) {
	    retdata = 0;
	    break;
	}
	/* What to free the list later. */
	pointlist = g_slist_append(pointlist, data);
	switch(list_type){
	    case MATECONF_VALUE_INT:
	    case MATECONF_VALUE_BOOL:
		clist = g_slist_append(clist, GINT_TO_POINTER(*(gint*)data));
		break;
	    case MATECONF_VALUE_FLOAT:
		clist = g_slist_append(clist, (gdouble*)data);
		break;
	    case MATECONF_VALUE_STRING:
		clist = g_slist_append(clist, *(gchar**)data);
		break;
	    case MATECONF_VALUE_SCHEMA:
		clist = g_slist_append(clist, *(MateConfSchema**)data);
		break;
	    default:
		PyErr_SetString(PyExc_TypeError, "Unknown MateConfValueType.");
		retdata = 0;
		break;
	}
    }

    if (retdata)
	ret = mateconf_client_set_list(MATECONF_CLIENT(self->obj), key, list_type,
	    clist, &err);

    for (tmplist = pointlist; tmplist; tmplist = tmplist->next) {
	g_free(tmplist->data);
    }
    g_slist_free(pointlist);
    g_slist_free(clist);

    if (pyg_error_check(&err) || !retdata)
	return NULL;
    return PyInt_FromLong(ret);
}

%%
override mateconf_value_get_car args
static PyObject *
_wrap_mateconf_value_get_car(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    MateConfValue* vobj;

    vobj = mateconf_value_get_car(pyg_boxed_get(self, MateConfValue));
    return pyg_boxed_new(MATECONF_TYPE_VALUE, vobj, TRUE, TRUE);
}

%%
override mateconf_value_get_cdr args
static PyObject *
_wrap_mateconf_value_get_cdr(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    MateConfValue* vobj;

    vobj = mateconf_value_get_cdr(pyg_boxed_get(self, MateConfValue));
    return pyg_boxed_new(MATECONF_TYPE_VALUE, vobj, TRUE, TRUE);
}
%%
override mateconf_value_get_list args
static PyObject *
_wrap_mateconf_value_get_list(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    MateConfValue *value;
    PyObject *pylist;
    GSList *values = NULL, *list;
    int i = 0;

    value = pyg_boxed_get(self, MateConfValue);
    if (value->type != MATECONF_VALUE_LIST) {
	PyErr_SetString(PyExc_TypeError, "mateconf value does not contain a list.");
	return NULL;
    }
    values = mateconf_value_get_list(value);

    pylist = PyTuple_New(g_slist_length(values));
    for (list = values; list; list = list->next) {
	PyObject *pyvalue;
	value = list->data;
	pyvalue = pyg_boxed_new(MATECONF_TYPE_VALUE, value, TRUE, TRUE);

	PyTuple_SetItem(pylist, i++, pyvalue);
    }
    
    return pylist;
}
%%
override mateconf_value_get_int noargs
static PyObject *
_wrap_mateconf_value_get_int(PyObject *self)
{
    int ret;
    MateConfValue *value;

    value = pyg_boxed_get(self, MateConfValue);
    if (value->type != MATECONF_VALUE_INT) {
	PyErr_SetString(PyExc_TypeError, "mateconf value does not contain an integer.");
	return NULL;
    }
    ret = mateconf_value_get_int(value);
    return PyInt_FromLong(ret);
}
%%
override mateconf_value_get_string noargs
static PyObject *
_wrap_mateconf_value_get_string(PyObject *self)
{
    const gchar *ret;
    MateConfValue *value;

    value = pyg_boxed_get(self, MateConfValue);
    if (value->type != MATECONF_VALUE_STRING) {
	PyErr_SetString(PyExc_TypeError, "mateconf value does not contain a string.");
	return NULL;
    }
    ret = mateconf_value_get_string(value);
    if (ret)
        return PyString_FromString(ret);
    Py_INCREF(Py_None);
    return Py_None;
}
%%
override mateconf_value_get_float noargs
static PyObject *
_wrap_mateconf_value_get_float(PyObject *self)
{
    double ret;
    MateConfValue *value;

    value = pyg_boxed_get(self, MateConfValue);
    if (value->type != MATECONF_VALUE_FLOAT) {
	PyErr_SetString(PyExc_TypeError, "mateconf value does not contain a float.");
	return NULL;
    }
    ret = mateconf_value_get_float(value);
    return PyFloat_FromDouble(ret);
}
%%
override mateconf_value_get_bool noargs
static PyObject *
_wrap_mateconf_value_get_bool(PyObject *self)
{
    int ret;
    PyObject *py_ret;
    MateConfValue *value;

    value = pyg_boxed_get(self, MateConfValue);
    if (value->type != MATECONF_VALUE_BOOL) {
	PyErr_SetString(PyExc_TypeError, "mateconf value does not contain a boolean.");
	return NULL;
    }
    ret = mateconf_value_get_bool(value);
    py_ret = ret ? Py_True : Py_False;
    Py_INCREF(py_ret);
    return py_ret;
}
%%
override mateconf_value_set_list kwargs
static PyObject *
_wrap_mateconf_value_set_list(PyObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "list", NULL };
    GSList *list;
    PyObject *py_list;
    int i, len;
    MateConfValue *value = pyg_boxed_get(self, MateConfValue);

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:MateConfValue.set_list", kwlist,
                                     &PyList_Type, &py_list))
        return NULL;
    if (value->type != MATECONF_VALUE_LIST) {
	PyErr_SetString(PyExc_TypeError, "mateconf value type must be list.");
	return NULL;
    }

    len = PyList_Size(py_list);
    for (i = 0, list = NULL; i < len; i++) {
        PyObject *item = PyList_GET_ITEM(py_list, i);
        if (!pyg_boxed_check(item, MATECONF_TYPE_VALUE)) {
            PyErr_SetString(PyExc_TypeError, "list elements must be of type mateconf.Value");
            g_slist_free(list);
            return NULL;
        }
        list = g_slist_append(list, pyg_boxed_get(item, MateConfValue));
    }
    mateconf_value_set_list(value, list);
    g_slist_free(list);
    Py_INCREF(Py_None);
    return Py_None;
}
%%
override mateconf_client_change_set_from_current
static PyObject *
_wrap_mateconf_client_change_set_from_current(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "keys", NULL };
    PyObject *py_list;
    const gchar **keys;
    GError *err = NULL;
    MateConfChangeSet *ret;
    int len, i;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:MateConfClient.change_set_from_current",
                                     kwlist, &PyList_Type, &py_list))
        return NULL;
    len = PyList_Size(py_list);
    keys = g_new(const gchar *, len + 1);
    for (i = 0; i < len; ++i) {
        PyObject *item = PyList_GET_ITEM(py_list, i);
        if (!PyString_Check(item)) {
            g_free(keys);
            PyErr_SetString(PyExc_TypeError, "list elements must be of type str");
            return NULL;
        }
        keys[i] = PyString_AsString(item);
    }
    keys[i] = NULL;
    ret = mateconf_client_change_set_from_currentv(MATECONF_CLIENT(self->obj), keys, &err);
    g_free(keys);
    if (pyg_error_check(&err))
        return NULL;
    /* pyg_boxed_new handles NULL checking */
    return pyg_boxed_new(MATECONF_TYPE_CHANGE_SET, ret, TRUE, TRUE);
}
%%
override mateconf_change_set_set_list kwargs
static PyObject *
_wrap_mateconf_change_set_set_list(PyObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "key", "list_type", "list", NULL };
    char *key;
    PyObject *py_list_type = NULL, *py_list;
    MateConfValueType list_type;
    int i, len;
    GSList *list;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOO!:MateConfChangeSet.set_list"
                                     , kwlist, &key, &py_list_type,
                                     &PyList_Type, &py_list))
        return NULL;
    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE, py_list_type, (gint *)&list_type))
        return NULL;

    len = PyList_Size(py_list);
    for (i = 0, list = NULL; i < len; i++) {
        PyObject *item = PyList_GET_ITEM(py_list, i);
        if (!pyg_boxed_check(item, MATECONF_TYPE_VALUE)) {
            PyErr_SetString(PyExc_TypeError, "list elements must be of type mateconf.Value");
            g_slist_free(list);
            return NULL;
        }
        list = g_slist_append(list, pyg_boxed_get(item, MateConfValue));
    }
    mateconf_change_set_set_list(pyg_boxed_get(self, MateConfChangeSet), key, list_type, list);
    g_slist_free(list);
    Py_INCREF(Py_None);
    return Py_None;
}

%%
define MateConfClient.get_value kwargs

static PyObject *
_wrap_mate_conf_client_get_value(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "key", NULL };
    char *key;
    GError *err = NULL;
    MateConfValue *value;
    PyObject *py_ret;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:MateConfClient.get_value", kwlist, &key))
        return NULL;
    
    value = mateconf_client_get(MATECONF_CLIENT(self->obj), key, &err);
    
    if (pyg_error_check(&err))
        return NULL;

    if (value == NULL) {
        PyErr_Format(PyExc_ValueError, "mateconf key %s has no value", key);
        return NULL;
    }

    switch (value->type)
    {
    case MATECONF_VALUE_INVALID:
        PyErr_SetString(PyExc_TypeError, "invalid value");
        py_ret = NULL;
        break;

    case MATECONF_VALUE_STRING:
        py_ret = PyString_FromString(mateconf_value_get_string(value));
        break;
    case MATECONF_VALUE_INT:
        py_ret = PyInt_FromLong(mateconf_value_get_int(value));
        break;
    case MATECONF_VALUE_FLOAT:
        py_ret = PyFloat_FromDouble(mateconf_value_get_float(value));
        break;
    case MATECONF_VALUE_BOOL:
        py_ret = PyBool_FromLong(mateconf_value_get_bool(value));
        break;

    case MATECONF_VALUE_SCHEMA:
    case MATECONF_VALUE_LIST:
    case MATECONF_VALUE_PAIR:
        PyErr_SetString(PyExc_TypeError, "value type not supported yet by this API");
        py_ret = NULL;
        break;
    default:
        py_ret = NULL;
    }
    mateconf_value_free(value);
    return py_ret;
}

%%
define MateConfClient.set_value kwargs

static PyObject *
_wrap_mate_conf_client_set_value(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "key", "val", NULL };
    char *key;
    PyObject *py_val;
    GError *err = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"sO:MateConfClient.set_value", kwlist, &key, &py_val))
        return NULL;
    if (pyg_boxed_check(py_val, MATECONF_TYPE_VALUE)) {
        mateconf_client_set(MATECONF_CLIENT(self->obj), key, pyg_boxed_get(py_val, MateConfValue), &err);
        if (pyg_error_check(&err))
            return NULL;
    } else {
        if (PyBool_Check(py_val)) {
            mateconf_client_set_bool(MATECONF_CLIENT(self->obj), key, PyInt_AsLong(py_val), &err);
        } else if (PyInt_Check(py_val)) {
            mateconf_client_set_int(MATECONF_CLIENT(self->obj), key, PyInt_AsLong(py_val), &err);
        } else if (PyFloat_Check(py_val)) {
            mateconf_client_set_float(MATECONF_CLIENT(self->obj), key, PyFloat_AsDouble(py_val), &err);
        } else if (PyString_Check(py_val)) {
            mateconf_client_set_string(MATECONF_CLIENT(self->obj), key, PyString_AsString(py_val), &err);
        } else if (PyUnicode_Check(py_val)) {
            PyObject *utf8_tmp = PyUnicode_AsUTF8String(py_val);
            if (!utf8_tmp)
                return NULL;
            mateconf_client_set_string(MATECONF_CLIENT(self->obj), key, PyString_AsString(utf8_tmp), &err);
            Py_DECREF(utf8_tmp);
        } else {
            PyErr_SetString(PyExc_TypeError, "value type not supported yet by this API");
            return NULL;
        }
        if (pyg_error_check(&err))
            return NULL;
    }
    
    Py_INCREF(Py_None);
    return Py_None;
}

%%
override mateconf_value_new_from_string kwargs
static PyObject *
_wrap_mateconf_value_new_from_string(PyObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "type", "str", NULL };
    PyObject *py_type = NULL;
    char *str;
    MateConfValueType type;
    GError *err = NULL;
    MateConfValue *ret;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os:value_new_from_string", kwlist, &py_type, &str))
        return NULL;
    if (pyg_enum_get_value(MATECONF_TYPE_VALUE_TYPE, py_type, (gpointer)&type))
        return NULL;

    if (type == MATECONF_VALUE_LIST || type == MATECONF_VALUE_PAIR) {
        PyErr_SetString(PyExc_ValueError, "MateConf value types LIST and PAIR are not valid for this function");
        return NULL;
    }
    
    ret = mateconf_value_new_from_string(type, str, &err);
    
    if (pyg_error_check(&err))
        return NULL;
    /* pyg_boxed_new handles NULL checking */
    return pyg_boxed_new(MATECONF_TYPE_VALUE, ret, TRUE, TRUE);
}
