/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#include "core_bindings.h"
#include "core_utils.h"
#include "qt_bindings.h"
#include "docstrings.h"

#include <Core.h>
#include <Property.h>
#include <PythonManager.h>
#include <Log.h>

void add_core_bindings(py::module_& m) {

    m.doc() = DOC(camitk_module);

    // --------------- Core ---------------

    m.attr("__version__") = camitk::Core::version();

    py::class_<camitk::Core> core(m, "Core");

    core.def_static("getTestDataDir",
                    &camitk::Core::getTestDataDir);

    core.def_static("version",
    []() {
        return camitk::Core::version();
    });

    core.def_static("shortVersion", []() {
        return camitk::Core::shortVersion();
    });

    core.def_static("getConfig", []() {
        return camitk::Core::getConfig();
    });

    core.def_static("getPaths", []() {
        return camitk::Core::getPaths();
    });

    // --------------- Log ---------------
    py::class_<camitk::Log> log(m, "Log");

    // log level enum
    // TODO change to enum_native when updating binding to pybind3
    // see https://pybind11.readthedocs.io/en/stable/classes.html#enumerations-and-internal-types
    py::enum_<camitk::InterfaceLogger::LogLevel>(log, "LogLevel")
    .value("NONE", camitk::InterfaceLogger::NONE)
    .value("ERROR", camitk::InterfaceLogger::ERROR)
    .value("WARNING", camitk::InterfaceLogger::WARNING)
    .value("INFO", camitk::InterfaceLogger::INFO)
    .value("TRACE", camitk::InterfaceLogger::TRACE)
    .export_values();

    log.def("setLogLevel",
    [](const camitk::InterfaceLogger::LogLevel & level) {
        camitk::Log::getLogger()->setLogLevel(level);
    });

    log.def("setMessageBoxLevel",
    [](const camitk::InterfaceLogger::LogLevel & level) {
        camitk::Log::getLogger()->setMessageBoxLevel(level);
    });

    log.def("setTimeStampInformation",
    [](const bool status) {
        camitk::Log::getLogger()->setTimeStampInformation(status);
    });

    log.def("setDebugInformation",
    [](const bool status) {
        camitk::Log::getLogger()->setDebugInformation(status);
    });

    // --------------- Utils ---------------
    m.def("getDebugInfo",
          &camitk::PythonManager::pythonEnvironmentDebugInfo);

    m.def("getPythonVersion",
          &camitk::PythonManager::getPythonVersion);


    // --------------- Property ---------------
    py::class_<camitk::Property> property(m, "Property", DOC(camitk_Property));

    property.def(py::init<QString, QVariant, QString, QString>(),
                 py::arg("name"),
                 py::arg("value"),
                 py::arg("description"),
                 py::arg("unit"),
                 DOC(camitk_Property_Property_1));

    property.def("getName",
                 &camitk::Property::getName);

    property.def("setReadOnly",
                 &camitk::Property::setReadOnly);

    property.def("getReadOnly",
                 &camitk::Property::getReadOnly);

    property.def("getDescription",
                 &camitk::Property::getDescription);

    property.def("getUnit",
                 &camitk::Property::getUnit);

    property.def("setAttribute",
                 &camitk::Property::setAttribute,
                 py::arg("attribute"),
                 py::arg("value"));

    // as the setEnumTypeName method is overloaded, we must be explicit to define
    // which one is to be called.
    // see https://pybind11.readthedocs.io/en/stable/classes.html#overloaded-methods
    // for `void Property::setEnumTypeName(QString)`
    property.def("setEnumTypeName",
                 py::overload_cast<QString>(&camitk::Property::setEnumTypeName),
                 py::arg("set the name of the enum"),
                 py::return_value_policy::reference);

    property.def("getAttribute",
                 &camitk::Property::getAttribute);

}

