/* LIBPIKA - The PIKA Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 *
 * pikamodule.h
 * (C) 1999 Austin Donnelly <austin@gimp.org>
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <https://www.gnu.org/licenses/>.
 */

#ifndef __PIKA_MODULE_H__
#define __PIKA_MODULE_H__

#include <gio/gio.h>
#include <gmodule.h>

#define __PIKA_MODULE_H_INSIDE__

#include <libpikamodule/pikamoduletypes.h>

#include <libpikamodule/pikamoduledb.h>

#undef __PIKA_MODULE_H_INSIDE__

G_BEGIN_DECLS


/**
 * PIKA_MODULE_ABI_VERSION:
 *
 * The version of the module system's ABI. Modules put this value into
 * #PikaModuleInfo's @abi_version field so the code loading the modules
 * can check if it was compiled against the same module ABI the modules
 * are compiled against.
 *
 *  PIKA_MODULE_ABI_VERSION is incremented each time one of the
 *  following changes:
 *
 *  - the libpikamodule implementation (if the change affects modules).
 *
 *  - one of the classes implemented by modules (currently #PikaColorDisplay,
 *    #PikaColorSelector and #PikaController).
 **/
#define PIKA_MODULE_ABI_VERSION 0x0005


/**
 * PikaModuleState:
 * @PIKA_MODULE_STATE_ERROR:       Missing pika_module_register() function
 *                                 or other error.
 * @PIKA_MODULE_STATE_LOADED:      An instance of a type implemented by
 *                                 this module is allocated.
 * @PIKA_MODULE_STATE_LOAD_FAILED: pika_module_register() returned %FALSE.
 * @PIKA_MODULE_STATE_NOT_LOADED:  There are no instances allocated of
 *                                 types implemented by this module.
 *
 * The possible states a #PikaModule can be in.
 **/
typedef enum
{
  PIKA_MODULE_STATE_ERROR,
  PIKA_MODULE_STATE_LOADED,
  PIKA_MODULE_STATE_LOAD_FAILED,
  PIKA_MODULE_STATE_NOT_LOADED
} PikaModuleState;


#define PIKA_MODULE_ERROR (pika_module_error_quark ())

GQuark  pika_module_error_quark (void) G_GNUC_CONST;

/**
 * PikaModuleError:
 * @PIKA_MODULE_FAILED: Generic error condition
 *
 * Types of errors returned by modules
 **/
typedef enum
{
  PIKA_MODULE_FAILED
} PikaModuleError;


/**
 * PikaModuleInfo:
 * @abi_version: The #PIKA_MODULE_ABI_VERSION the module was compiled against.
 * @purpose:     The module's general purpose.
 * @author:      The module's author.
 * @version:     The module's version.
 * @copyright:   The module's copyright.
 * @date:        The module's release date.
 *
 * This structure contains information about a loadable module.
 **/
struct _PikaModuleInfo
{
  guint32  abi_version;
  gchar   *purpose;
  gchar   *author;
  gchar   *version;
  gchar   *copyright;
  gchar   *date;
};


/**
 * PikaModuleQueryFunc:
 * @module:  The module responsible for this loadable module.
 *
 * The signature of the query function a loadable PIKA module must
 * implement. In the module, the function must be called [func@Module.query].
 *
 * [class@Module] will copy the returned [struct@ModuleInfo], so the
 * module doesn't need to keep these values around (however in most
 * cases the module will just return a pointer to a constant
 * structure).
 *
 * Returns: The info struct describing the module.
 **/
typedef const PikaModuleInfo * (* PikaModuleQueryFunc)    (GTypeModule *module);

/**
 * PikaModuleRegisterFunc:
 * @module:  The module responsible for this loadable module.
 *
 * The signature of the register function a loadable PIKA module must
 * implement.  In the module, the function must be called
 * [func@Module.register].
 *
 * When this function is called, the module should register all the types
 * it implements with the passed @module.
 *
 * Returns: Whether the registration was succesfull
 **/
typedef gboolean               (* PikaModuleRegisterFunc) (GTypeModule *module);


/* PikaModules have to implement these */
G_MODULE_EXPORT const PikaModuleInfo * pika_module_query    (GTypeModule *module);
G_MODULE_EXPORT gboolean               pika_module_register (GTypeModule *module);


#define PIKA_TYPE_MODULE            (pika_module_get_type ())
#define PIKA_MODULE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_MODULE, PikaModule))
#define PIKA_MODULE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_MODULE, PikaModuleClass))
#define PIKA_IS_MODULE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_MODULE))
#define PIKA_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_MODULE))
#define PIKA_MODULE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_MODULE, PikaModuleClass))


typedef struct _PikaModulePrivate PikaModulePrivate;
typedef struct _PikaModuleClass   PikaModuleClass;

struct _PikaModule
{
  GTypeModule        parent_instance;

  PikaModulePrivate *priv;
};

struct _PikaModuleClass
{
  GTypeModuleClass  parent_class;

  void (* modified) (PikaModule *module);

  /* Padding for future expansion */
  void (* _pika_reserved1) (void);
  void (* _pika_reserved2) (void);
  void (* _pika_reserved3) (void);
  void (* _pika_reserved4) (void);
  void (* _pika_reserved5) (void);
  void (* _pika_reserved6) (void);
  void (* _pika_reserved7) (void);
  void (* _pika_reserved8) (void);
};


GType                  pika_module_get_type       (void) G_GNUC_CONST;

PikaModule           * pika_module_new            (GFile           *file,
                                                   gboolean         auto_load,
                                                   gboolean         verbose);

GFile                * pika_module_get_file       (PikaModule      *module);

void                   pika_module_set_auto_load  (PikaModule      *module,
                                                   gboolean         auto_load);
gboolean               pika_module_get_auto_load  (PikaModule      *module);

gboolean               pika_module_is_on_disk     (PikaModule      *module);
gboolean               pika_module_is_loaded      (PikaModule      *module);

const PikaModuleInfo * pika_module_get_info       (PikaModule      *module);
PikaModuleState        pika_module_get_state      (PikaModule      *module);
const gchar          * pika_module_get_last_error (PikaModule      *module);

gboolean               pika_module_query_module   (PikaModule      *module);


G_END_DECLS

#endif  /* __PIKA_MODULE_H__ */
