#include <Python.h>

#include "pylcm_subscription.h"

//#define dbg(...) fprintf (stderr, __VA_ARGS__)
#define dbg(...)

// to support python 2.5 and earlier
#ifndef Py_TYPE
#define Py_TYPE(ob) (((PyObject *) (ob))->ob_type)
#endif

// to support python 3.9.0a3 and earlier
#if PY_VERSION_HEX < 0x030900A4
#define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void) 0)
#endif

extern PyTypeObject pylcmeventlog_type;
extern PyTypeObject pylcm_type;
extern PyTypeObject pylcm_subscription_type;

/* module initialization */

static PyMethodDef lcmmod_methods[] = {
    {NULL, NULL}, /* sentinel */
};
PyDoc_STRVAR(lcmmod_doc, "LCM python extension modules");

// macro to make module init portable between python 2 and 3
#if PY_MAJOR_VERSION >= 3
#define MOD_DEF(ob, name, doc, methods)                \
    static struct PyModuleDef moduledef = {            \
        PyModuleDef_HEAD_INIT, name, doc, -1, methods, \
    };                                                 \
    ob = PyModule_Create(&moduledef);
#else
#define MOD_DEF(ob, name, doc, methods) ob = Py_InitModule3(name, methods, doc);
#endif

#if __GNUC__ >= 4 || defined(__clang__)
__attribute__((visibility("default")))
#endif
PyMODINIT_FUNC
#if PY_MAJOR_VERSION >= 3
PyInit__lcm(void)
#else
init_lcm(void)
#endif
{
    PyObject *m;

    Py_SET_TYPE(&pylcmeventlog_type, &PyType_Type);
    Py_SET_TYPE(&pylcm_type, &PyType_Type);
    Py_SET_TYPE(&pylcm_subscription_type, &PyType_Type);

    MOD_DEF(m, "_lcm", lcmmod_doc, lcmmod_methods);

    Py_INCREF(&pylcmeventlog_type);
    if (PyModule_AddObject(m, "EventLog", (PyObject *) &pylcmeventlog_type) != 0) {
#if PY_MAJOR_VERSION >= 3
        return NULL;  // in python 3 return NULL on error
#else
        return;
#endif
    }

    Py_INCREF(&pylcm_type);
    if (PyModule_AddObject(m, "LCM", (PyObject *) &pylcm_type) != 0) {
#if PY_MAJOR_VERSION >= 3
        return NULL;  // in python 3 return NULL on error
#else
        return;
#endif
    }

    Py_INCREF(&pylcm_subscription_type);
    if (PyModule_AddObject(m, "LCMSubscription", (PyObject *) &pylcm_subscription_type) != 0) {
#if PY_MAJOR_VERSION >= 3
        return NULL;  // in python 3 return NULL on error
#else
        return;
#endif
    }
#if PY_MAJOR_VERSION >= 3
    return m;  // in python 3, we must return the PyObject
#endif
}
