#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif

/* include this first, before NO_IMPORT_PYGOBJECT is defined */
#include <pygobject.h>
#include <pygtk/pygtk.h>
#include <diacanvas/dia-canvas.h>

static PyObject *
diacanvaspoint_from_value(const GValue *value)
{
	DiaPoint *point = (DiaPoint*) g_value_get_boxed(value);
	g_message (G_STRLOC": %f %f", point->x, point->y);
	return Py_BuildValue("(dd)", point->x, point->y);
}

static int
diacanvaspoint_to_value (GValue *value, PyObject *py_point)
{
	int i;
	PyObject *sitem;
	gdouble val[2];
	DiaPoint point;

	if (PySequence_Length(py_point) != 2) {
		PyErr_SetString(PyExc_TypeError,
				"argument must be a 2 tuple of floats.");
		return -1;
	}

	for (i = 0; i < 2; i++) {
		sitem = PySequence_GetItem(py_point, i);
		Py_DECREF(sitem);
		sitem = PyNumber_Float(sitem);
		if (sitem)
			val[i] = PyFloat_AsDouble(sitem);
		else {
			PyErr_Clear();
			PyErr_SetString(PyExc_TypeError,
					"sequence item not a float");
			return -1;
		}
		Py_DECREF(sitem);
	}
	point.x = val[0];
	point.y = val[1];

	g_value_set_boxed (value, &point);

	return 0;
}

static PyObject *
diacanvasrectangle_from_value(const GValue *value)
{
	DiaRectangle *rect = (DiaRectangle*) g_value_get_boxed (value);
	return Py_BuildValue("(dddd)", rect->left, rect->top,
				rect->right, rect->bottom);
}

static int
diacanvasrectangle_to_value (GValue *value, PyObject *py_rect)
{
	int i;
	PyObject *sitem;
	gdouble val[4];
	DiaRectangle rect;

	if (PySequence_Length(py_rect) != 4) {
		PyErr_SetString(PyExc_TypeError,
				"argument must be a 4 tuple of floats.");
		return -1;
	}

	for (i = 0; i < 4; i++) {
		sitem = PySequence_GetItem(py_rect, i);
		Py_DECREF(sitem);
		sitem = PyNumber_Float(sitem);
		if (sitem)
			val[i] = PyFloat_AsDouble(sitem);
		else {
			PyErr_Clear();
			PyErr_SetString(PyExc_TypeError,
					"sequence item not a float");
			return -1;
		}
		Py_DECREF(sitem);
	}
	rect.left = val[0];
	rect.top = val[1];
	rect.right = val[2];
	rect.bottom = val[3];

	g_value_set_boxed (value, &rect);

	return 0;
}

static PyObject *
diacanvasaffine_from_value(const GValue *value)
{
	gdouble *a = (gdouble*) g_value_get_boxed (value);
	return Py_BuildValue("(dddddd)", a[0], a[1], a[2], a[3], a[4], a[5]);
}

static int
diacanvasaffine_to_value (GValue *value, PyObject *py_affine)
{
	int i;
	PyObject *sitem;
	gdouble a[6];

	if (PySequence_Length(py_affine) != 6) {
		PyErr_SetString(PyExc_TypeError,
				"argument must be a 6 tuple of floats.");
		return -1;
	}

	for (i = 0; i < 6; i++) {
		sitem = PySequence_GetItem(py_affine, i);
		Py_DECREF(sitem);
		sitem = PyNumber_Float(sitem);
		if (sitem)
			a[i] = PyFloat_AsDouble(sitem);
		else {
			PyErr_Clear();
			PyErr_SetString(PyExc_TypeError,
					"sequence item not a float");
			return -1;
		}
		Py_DECREF(sitem);
	}

	g_value_set_boxed (value, a);

	return 0;
}

void pydiageometry_register_classes (PyObject *d);

extern PyMethodDef pydiageometry_functions[];

DL_EXPORT(void)
initgeometry (void)
{
	PyObject *m, *d;

	/* Standard initialization: */
	init_pygobject ();
	init_pygtk ();

	pyg_register_boxed_custom (DIA_TYPE_POINT,
				   diacanvaspoint_from_value,
				   diacanvaspoint_to_value);
	pyg_register_boxed_custom (DIA_TYPE_RECTANGLE,
				   diacanvasrectangle_from_value,
				   diacanvasrectangle_to_value);
	pyg_register_boxed_custom (DIA_TYPE_AFFINE,
				   diacanvasaffine_from_value,
				   diacanvasaffine_to_value);

	m = Py_InitModule ("diacanvas.geometry", pydiageometry_functions);
	d = PyModule_GetDict (m);

	pydiageometry_register_classes (d);

	if (PyErr_Occurred ()) {
		Py_FatalError ("can't initialise module diacanvas.geometry");
	}
}

