/* Chrysalide - Outil d'analyse de fichiers binaires
 * core-ui.c - plugin permettant des extensions UI en Python
 *
 * Copyright (C) 2025 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  Chrysalide is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Chrysalide 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "core-ui.h"


#include <stdbool.h>


#include <i18n.h>
#include <plugins/self.h>


#include "bindings.h"
#include "core-ui-int.h"



/* Note la nature du chargement */
static bool _standalone = true;



/* ---------------------- COMPOSITION DE NOUVEAU GREFFON NATIF ---------------------- */


/* Initialise la classe des greffons de support Python. */
static void g_pychrysalide_plugin_ui_class_init(GPyChrysalidePluginUIClass *);

/* Initialise une instance de greffon de support Python. */
static void g_pychrysalide_plugin_ui_init(GPyChrysalidePluginUI *);

/* Supprime toutes les références externes. */
static void g_pychrysalide_plugin_ui_dispose(GPyChrysalidePluginUI *);

/* Procède à la libération totale de la mémoire. */
static void g_pychrysalide_plugin_ui_finalize(GPyChrysalidePluginUI *);



/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */


/* Prend acte de l'activation du greffon. */
static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *);



/* ---------------------------------------------------------------------------------- */
/*                        COMPOSITION DE NOUVEAU GREFFON NATIF                        */
/* ---------------------------------------------------------------------------------- */


/* Indique le type défini pour un greffon de liaison Python */
G_DEFINE_TYPE(GPyChrysalidePluginUI, g_pychrysalide_plugin_ui, G_TYPE_PYCHRYSALIDE_PLUGIN);


NATIVE_PLUGIN_ENTRYPOINT(g_pychrysalide_plugin_ui_new);


/******************************************************************************
*                                                                             *
*  Paramètres  : class = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe des greffons de support Python.         *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_pychrysalide_plugin_ui_class_init(GPyChrysalidePluginUIClass *class)
{
    GObjectClass *object;                   /* Autre version de la classe  */
    GPluginModuleClass *plugin;             /* Version parente de la classe*/

    object = G_OBJECT_CLASS(class);

    object->dispose = (GObjectFinalizeFunc/* ! */)g_pychrysalide_plugin_ui_dispose;
    object->finalize = (GObjectFinalizeFunc)g_pychrysalide_plugin_ui_finalize;

    plugin = G_PLUGIN_MODULE_CLASS(class);

    plugin->enable = (pg_management_fc)g_pychrysalide_plugin_ui_enable;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : plugin = instance à initialiser.                             *
*                                                                             *
*  Description : Initialise une instance de greffon de support Python.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_pychrysalide_plugin_ui_init(GPyChrysalidePluginUI *plugin)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : plugin = instance d'objet GLib à traiter.                    *
*                                                                             *
*  Description : Supprime toutes les références externes.                     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_pychrysalide_plugin_ui_dispose(GPyChrysalidePluginUI *plugin)
{
    G_OBJECT_CLASS(g_pychrysalide_plugin_ui_parent_class)->dispose(G_OBJECT(plugin));

}


/******************************************************************************
*                                                                             *
*  Paramètres  : plugin = instance d'objet GLib à traiter.                    *
*                                                                             *
*  Description : Procède à la libération totale de la mémoire.                *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_pychrysalide_plugin_ui_finalize(GPyChrysalidePluginUI *plugin)
{
    G_OBJECT_CLASS(g_pychrysalide_plugin_ui_parent_class)->finalize(G_OBJECT(plugin));

}


/******************************************************************************
*                                                                             *
*  Paramètres  : filename = nom du fichier à charger.                         *
*                                                                             *
*  Description : Crée un module pour un greffon de support Python.            *
*                                                                             *
*  Retour      : Adresse de la structure mise en place.                       *
*                                                                             *
*  Remarques   : Le transfert de propriétée du module est total.              *
*                                                                             *
******************************************************************************/

GPluginModule *g_pychrysalide_plugin_ui_new(GModule *module)
{
    GPyChrysalidePluginUI *result;          /* Structure à retourner       */

    result = g_object_new(G_TYPE_PYCHRYSALIDE_PLUGIN_UI, NULL);

    if (!g_pychrysalide_plugin_ui_create(result, module))
        g_clear_object(&result);

    return G_PLUGIN_MODULE(result);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : plugin = instance à initialiser pleinement.                  *
*                module = module système correspondant.                       *
*                                                                             *
*  Description : Met en place un module pour un greffon de support Python.    *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : Le transfert de propriétée du module est total.              *
*                                                                             *
******************************************************************************/

bool g_pychrysalide_plugin_ui_create(GPyChrysalidePluginUI *plugin, GModule *module)
{
    bool result;                            /* Bilan à retourner           */

    result = g_pychrysalide_plugin_create(G_PYCHRYSALIDE_PLUGIN(plugin), module);

    return result;

}



/* ---------------------------------------------------------------------------------- */
/*                       IMPLEMENTATION DES FONCTIONS DE CLASSE                       */
/* ---------------------------------------------------------------------------------- */


/******************************************************************************
*                                                                             *
*  Paramètres  : plugin = greffon à manipuler.                                *
*                                                                             *
*  Description : Prend acte de l'activation du greffon.                       *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static bool g_pychrysalide_plugin_ui_enable(GPyChrysalidePluginUI *plugin)
{
    bool result;                            /* Bilan à retourner           */
    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
    int ret;                                /* Bilan de préparatifs        */

    _standalone = false;

    /* Chargement du module pour Python */

    ret = PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalideui);

    if (ret == -1)
    {
        g_plugin_module_log_simple_message(G_PLUGIN_MODULE(plugin),
                                           LMT_ERROR,
                                           _("Can not extend the existing table of Python built-in modules."));

        result = false;
        goto done;

    }

    Py_Initialize();

    gstate = PyGILState_Ensure();

    G_PYCHRYSALIDE_PLUGIN(plugin)->py_module = PyImport_ImportModule("pychrysalide");

    /**
     * Pour mémoire, une situation concrête conduisant à un échec :
     * le paquet python3-gi-dbg n'est pas installé alors que le
     * programme est compilé en mode débogage.
     *
     * Dans ce cas, pygobject_init(-1, -1, -1) échoue, et Py_Initialize()
     * le laisse rien filtrer...
     *
     * En mode autonome, le shell Python remonte bien l'erreur par contre.
     */

    // TODO : check (2025)

    result = (G_PYCHRYSALIDE_PLUGIN(plugin)->py_module != NULL);

    PyGILState_Release(gstate);

 done:

    return result;

}



/* ---------------------------------------------------------------------------------- */
/*                             POINT D'ENTREE POUR PYTHON                             */
/* ---------------------------------------------------------------------------------- */


/******************************************************************************
*                                                                             *
*  Paramètres  : -                                                            *
*                                                                             *
*  Description : Point d'entrée pour l'initialisation de Python.              *
*                                                                             *
*  Retour      : ?                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

PyMODINIT_FUNC PyInit_pychrysalideui(void)
{
    PyObject *result;                       /* Module Python à retourner   */
    pyinit_details_t details;               /* Détails de chargement       */

    details.standalone = _standalone;

    details.populate_extra = NULL;
    details.create_self = g_pychrysalide_plugin_ui_new;

    result = init_python_pychrysalide_module(&details);

    return result;

}