#include <Python.h>
#include <iostream>
#include <string>

class Test {
public:
    Test() = default;
    ~Test()
    {
        Py_DECREF(test);
        Py_DECREF(object);
    }
    void create()
    {
        test = Py_BuildValue("s", "Hello World from a method in Embedded Python!!!");
        std::cout << "test " << test->ob_refcnt << std::endl;
        std::string moduleName = "sklearn.svm.SVC";
        PyObject* pyModuleName = PyUnicode_FromString(moduleName.c_str());
        std::cout << "py_module_name " << pyModuleName->ob_refcnt << std::endl;
        object = PyImport_AddModuleObject(pyModuleName);
        if (PyErr_Occurred()) {
            std::cerr << "Couldn't import module " + moduleName;
            Py_XDECREF(test);
            Py_XDECREF(object);
            Py_XDECREF(pyModuleName);
            exit(1);
        }
        std::cout << "module " << object->ob_refcnt << std::endl;
        Py_XDECREF(pyModuleName);
    }
    PyObject* test;
    PyObject* object;

};

void print(PyObject* object, std::string name)
{
    std::cout << name << " " << object->ob_refcnt << std::endl;
}

int main(int argc, char* argv[])
{
    Py_Initialize();
    std::string moduleName = "sklearn.svm";
    std::cout << "1a" << std::endl;
    PyObject* module = PyImport_ImportModule(moduleName.c_str());
    if (PyErr_Occurred()) {
        std::cerr << "Couldn't import module " << moduleName;
        exit(1);
    }
    print(module, "module");
    std::cout << "1b" << std::endl;
    std::string className = "SVC";
    PyObject* classObject = PyObject_GetAttrString(module, className.c_str());
    if (PyErr_Occurred()) {
        std::cerr << "Couldn't find class " << className;
        exit(1);
    }
    print(classObject, "classObject");
    std::cout << "1c" << std::endl;
    PyObject* instance = PyObject_CallObject(classObject, NULL);
    if (PyErr_Occurred()) {
        std::cerr << "Couldn't create instance of class " << className;
        exit(1);
    }
    print(instance, "instance");
    std::cout << std::string(40, '-') << std::endl;
    print(module, "module");
    print(classObject, "classObject");
    print(instance, "instance");
    std::cout << "decref instance" << std::endl;
    Py_DECREF(instance);
    std::cout << "decref classobject" << std::endl;
    Py_DECREF(classObject);
    std::cout << "decref module" << std::endl;
    Py_DECREF(module);
    std::cout << std::string(40, '-') << std::endl;
    print(module, "after decref module");
    print(classObject, "after decref classObject");
    print(instance, "after decref instance");
    std::cout << "**call finalize" << std::endl;
    Py_Finalize();
    std::cout << "**after finalize" << std::endl;
    return 0;
}