#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include "cmunipack.h"
#include "framesetclass.h"
#include "magdevcurveclass.h"

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

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

static void
MagDevCurve_dealloc(MagDevCurve* 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
MagDevCurve_init(MagDevCurve *self, PyObject *param, PyObject *kwds)
{
	int res, aperture, comp = CMPACK_MFIND_AUTO;
	double clip = 0;
	FrameSet *fset;
	CmpackMuniFind *lc;

	static char *kwlist[] = {"fset", "aperture", "comp", "clip", NULL};
	if (!PyArg_ParseTupleAndKeywords(param, kwds, "O!i|id", kwlist, &FrameSetType, 
		&fset, &aperture, &comp, &clip))
		return -1;

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

	lc = cmpack_mfind_init();
	cmpack_mfind_set_aperture(lc, aperture);
	if (comp>=0)
		cmpack_mfind_set_comparison(lc, comp);
	if (clip>0 && clip<=100)
		cmpack_mfind_set_threshold(lc, clip);
	
	res = cmpack_mfind(lc, fset->f, &self->t.f, CMPACK_MFIND_DEFAULT);
	if (res==0)
		self->comp_star = cmpack_mfind_get_comparison(lc);
	cmpack_mfind_destroy(lc);
	if (res!=0) {
		cmpack_error(res);
		return -1;
	}

	return 0;
}

static PyObject *
MagDevCurve_object_id(MagDevCurve *self, void *data)
{
	int object_id, column;

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

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

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

	return PyLong_FromLong(object_id);
}

static PyObject *
MagDevCurve_comp_star(MagDevCurve *self, void *data)
{
	if (!self->t.f)
		return err_closed();

	if (self->comp_star>=0)
		return PyLong_FromLong(self->comp_star);
	Py_RETURN_NONE;
}

static PyObject *
MagDevCurve_go_to(MagDevCurve *self, PyObject *args)
{
	int f, object_id, res, column;

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

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

	column = cmpack_tab_find_column(self->t.f, "INDEX");
	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 && object_id==f)
			Py_RETURN_TRUE;
		res = cmpack_tab_next(self->t.f);
	}
	Py_RETURN_FALSE;
}

static PyObject *
MagDevCurve_copy(MagDevCurve *self, PyObject *args)
{
	int res;
	CmpackTable *newf; 

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

	newf = cmpack_tab_init(CMPACK_TABLE_TRACKLIST);
	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 MagDevCurve_FromHandle(self->t.f);
}

static PyGetSetDef MagDevCurve_getset[] = {
	{"object_id", (getter)MagDevCurve_object_id, NULL,
	"Get object identifier from active object"},

	{"comp_star", (getter)MagDevCurve_comp_star, NULL,
	"Get identifier of the comparison star"},

	{NULL}
};

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

	{"go_to", (PyCFunction)MagDevCurve_go_to, METH_VARARGS,
	"Activate an object specified by its identifier"},

    {NULL}  /* Sentinel */
};

PyTypeObject MagDevCurveType = {
    PyObject_HEAD_INIT(NULL)
    .tp_name = "cmpack.MagDevCurve",          /*tp_name*/
	.tp_basicsize = sizeof(MagDevCurve),           /*tp_basicsize*/
    .tp_dealloc = (destructor)MagDevCurve_dealloc,			/*tp_dealloc*/
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /*tp_flags*/
    .tp_doc = "MagDev curve",			/* tp_doc */
    .tp_methods = MagDevCurve_methods,           /* tp_methods */
    .tp_getset = MagDevCurve_getset,            /* tp_getset */
    .tp_base = &TableType,                         /* tp_base */
    .tp_init = (initproc)MagDevCurve_init,      /* tp_init */
    .tp_new = MagDevCurve_new                 /* tp_new */
};

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

PyTypeObject *MagDevCurve_Type(void)
{
	return &MagDevCurveType;
}
