#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include "cmunipack.h"
#include "framesetclass.h"
#include "apdevcurveclass.h"

PyObject *cmpack_error(int code);
PyObject *err_closed(void);

static PyObject *
ApDevCurve_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    ApDevCurve *self = (ApDevCurve*)type->tp_alloc(type, 0);
    if (self != NULL) 
		self->t.f = NULL;
    return (PyObject *)self;
}

static void
ApDevCurve_dealloc(ApDevCurve* self)
{
	if (self->t.f) {
		cmpack_tab_destroy(self->t.f);
		self->t.f = NULL;
	}
    self->t.ob_base.ob_type->tp_free((PyObject*)self);
}


static int
ApDevCurve_init(ApDevCurve *self, PyObject *param, PyObject *kwds)
{
	int i, res, *items;
	FrameSet *fset;
	PyObject *comp = NULL, *check = NULL;
	CmpackADCurve *lc;

	static char *kwlist[] = {"fset", "comp_list", "check_list", NULL};
	if (!PyArg_ParseTupleAndKeywords(param, kwds, "O!O!O!", kwlist, &FrameSetType, &fset, 
		&PyList_Type, &comp, &PyList_Type, &check))
		return -1;

	if (self->t.f) {
		cmpack_tab_destroy(self->t.f);
		self->t.f = NULL;
	}

	lc = cmpack_adcurve_init();

	if (comp) {
		Py_ssize_t count = PyList_Size(comp);
		if (count>0) {
			items = cmpack_malloc(count*sizeof(int));
			for (i=0; i<count; i++)
				items[i] = PyLong_AsLong(PyList_GetItem(comp, i));
			cmpack_adcurve_set_comp(lc, items, (int)count);
			cmpack_free(items);
		}
	}
	if (check) {
		Py_ssize_t count = PyList_Size(check);
		if (count>0) {
			items = cmpack_malloc(count*sizeof(int));
			for (i=0; i<count; i++)
				items[i] = PyLong_AsLong(PyList_GetItem(check, i));
			cmpack_adcurve_set_check(lc, items, (int)count);
			cmpack_free(items);
		}
	}

	res = cmpack_adcurve(lc, fset->f, &self->t.f, CMPACK_ADCURVE_DEFAULT);
	cmpack_adcurve_destroy(lc);
	if (res!=0) {
		cmpack_error(res);
		return -1;
	}

	return 0;
}

static PyObject *
ApDevCurve_filter(ApDevCurve *self, void *data)
{
	const char *filter;

	if (!self->t.f)
		return err_closed();

	filter = cmpack_tab_gkys(self->t.f, "filter");
	if (filter)
		return PyUnicode_FromString(filter);
	Py_RETURN_NONE;
}

static PyObject *
ApDevCurve_aperture(ApDevCurve *self, void *data)
{
	int aperture, column;

	if (!self->t.f)
		return err_closed();

	column = cmpack_tab_find_column(self->t.f, "APERTURE");
	if (column<0)
		Py_RETURN_NONE;

	if (cmpack_tab_gtdi(self->t.f, column, &aperture)!=0)
		Py_RETURN_NONE;

	return PyLong_FromLong(aperture);
}

static PyObject *
ApDevCurve_go_to(ApDevCurve *self, PyObject *args)
{
	int f, aperture, res, column;

	if (!self->t.f)
		return err_closed();

	if (!PyArg_ParseTuple(args, "i", &aperture))
		return NULL;

	column = cmpack_tab_find_column(self->t.f, "APERTURE");
	if (column<0)
		Py_RETURN_FALSE;

	res = cmpack_tab_rewind(self->t.f);
	while (res==0) {
		if (cmpack_tab_gtdi(self->t.f, column, &f)==0 && aperture==f)
			Py_RETURN_TRUE;
		res = cmpack_tab_next(self->t.f);
	}
	Py_RETURN_FALSE;
}

static PyObject *
ApDevCurve_copy(ApDevCurve *self, PyObject *args)
{
	int res;
	CmpackTable *newf; 

	if (!self->t.f)
		return err_closed();

	newf = cmpack_tab_init(CMPACK_TABLE_APERTURES);
	if (!newf) {
		PyErr_SetString(PyExc_MemoryError, "Memory allocation error.");
		return NULL;
	}
	res = cmpack_tab_copy(newf, self->t.f);
	if (res!=0) {
		cmpack_tab_destroy(newf);
		return cmpack_error(res);
	}
	return ApDevCurve_FromHandle(self->t.f);
}

static PyGetSetDef ApDevCurve_getset[] = {
	{"filter", (getter)ApDevCurve_filter, NULL,
	"Color filter designation"},

	{"aperture", (getter)ApDevCurve_aperture, NULL,
	"Get aperture identifier from active record"},

	{NULL}
};

static PyMethodDef ApDevCurve_methods[] = {
	{"copy", (PyCFunction)ApDevCurve_copy, METH_NOARGS,
	"Make copy of the frame set"},

	{"go_to", (PyCFunction)ApDevCurve_go_to, METH_VARARGS,
	"Activate a frame specified by its identifier"},

    {NULL}  /* Sentinel */
};

PyTypeObject ApDevCurveType = {
    PyObject_HEAD_INIT(NULL)
    .tp_name = "cmpack.ApDevCurve",          /*tp_name*/
	.tp_basicsize = sizeof(ApDevCurve),           /*tp_basicsize*/
    .tp_dealloc = (destructor)ApDevCurve_dealloc,			/*tp_dealloc*/
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /*tp_flags*/
    .tp_doc = "Aperture-Deviations curve",			/* tp_doc */
    .tp_methods = ApDevCurve_methods,           /* tp_methods */
    .tp_getset = ApDevCurve_getset,            /* tp_getset */
    .tp_base = &TableType,                         /* tp_base */
    .tp_init = (initproc)ApDevCurve_init,      /* tp_init */
    .tp_new = ApDevCurve_new                 /* tp_new */
};

PyObject *
ApDevCurve_FromHandle(CmpackTable *f)
{
	Table *pDoc = PyObject_New(Table, &ApDevCurveType);
	if (pDoc) {
		pDoc->f = f;
	}
	return (PyObject*)pDoc;
}


PyTypeObject *ApDevCurve_Type(void)
{
	return &ApDevCurveType;
}
