/***************************************************************************
                    libeboxyplugin.c - eboxy plugin client library
                             -------------------
    begin                : Thu Oct 3 2002
    copyright            : (C) 2002 by Paul Eggleton
    email                : bluelightning@bluelightning.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "eboxyplugin.h"
#include "pluginconstants.h"
#include "errors.h"

/* These define what version of eboxy this library comes from (must be kept
   up-to-date! */
#define CLIENTLIB_VERSION_MAJOR    0
#define CLIENTLIB_VERSION_MINOR    4
#define CLIENTLIB_VERSION_SUBMINOR 1

/* NOTE 1:
 *
 * To add an exported function here, you need to add the following:
 * 1. a function pointer
 * 2. a name entry in the dynamicfns array (I suggest you add it to the end
 *    for safety)
 * 3. a line in eboxy_clientlib_init that links the function pointer to the
 *    entry in dynamicfns (by way of the "func" member)
 * 4. a wrapper function and a copy of the definition of that function in
 *    eboxyplugin.h.
 *
 * It is done in this way so that resolving the functions in a loop in
 * eboxy_init_plugin is easy.
 */

/* NOTE 2:
 * Unless you are modifying eboxy itself, you should not need to modify this
 * library. */

/* Function pointers */
int (*fptr_findObject)(const char *, const char *) = NULL;
const char *(*fptr_typeOfObject)(const char *) = NULL;
char *(*fptr_getPropertyAsString)(const char *, const char *) = NULL;
int (*fptr_setPropertyAsString)(const char *, const char *, const char *) = NULL;
char *(*fptr_callMethod)(const char *, const char *, int, const char*[]) = NULL;
int (*fptr_registerObject)(const char *, int id) = NULL;
int (*fptr_registerPropertyDL)(const char *, const char *, int id, const char *, const char *) = NULL;
int (*fptr_registerEventHandlerDL)(const char *, const char *, int id, const char *) = NULL;
int (*fptr_registerMethodDL)(const char *, const char *, int id, int numargs, const char *) = NULL;
int (*fptr_fireEvent)(const char *, const char *, int id) = NULL;
const struct plugin_info *(*fptr_getPluginInfo)(const char *) = NULL;
void (*fptr_setPluginInfo)(int, const char *, const char *) = NULL;
void (*fptr_requestUnload)(int) = NULL;
int (*fptr_changePage)(const char *) = NULL;
int (*fptr_loadXMLFile)(const char *, const char *) = NULL;
int (*fptr_performAction)(const char *) = NULL;
int (*fptr_unregisterObject)(const char *, int id) = NULL;
int (*fptr_unregisterEventHandlerDL)(const char *, const char *, int id) = NULL;
int (*fptr_createWidget)(const char *, const char *, const char *) = NULL;
int (*fptr_createPage)(const char *) = NULL;
int (*fptr_cloneWidget)(const char *, const char *) = NULL;
int (*fptr_deleteWidget)(const char *) = NULL;
int (*fptr_deletePage)(const char *) = NULL;
int (*fptr_runScript)(const char *, int) = NULL;

/* Struct type to handle the function array */
struct dynamicfn {
	char *name;
	void **func;
};

/* Array to hold the names and function pointer pointers (no, that's not a typo) */
struct dynamicfn dynamicfns[] = {
  {"findObject",               NULL},
  {"typeOfObject",             NULL},
  {"getPropertyAsString",      NULL},
  {"setPropertyAsString",      NULL},
  {"callMethod",               NULL},
  {"registerObject",           NULL},
  {"registerPropertyDL",       NULL},
  {"registerEventHandlerDL",   NULL},
  {"registerMethodDL",         NULL},
  {"fireEvent",                NULL},
  {"getPluginInfo",            NULL},
  {"setPluginInfo",            NULL},
  {"requestUnload",            NULL},
  {"changePage",               NULL},
  {"loadXMLFile",              NULL},
  {"performAction",            NULL},
  {"unregisterObject",         NULL},
  {"unregisterEventHandlerDL", NULL},
  {"createWidget",             NULL},
  {"createPage",               NULL},
  {"cloneWidget",              NULL},
  {"deleteWidget",             NULL},
  {"deletePage",               NULL},
  {"runScript",                NULL}
};

int internal_plugin_id;

int eboxy_clientlib_init(void *(*resolverfn)(char *), int plugin_id) {
  void *funcptr = NULL;
  int i=0;

  /* Careful: order and number must match the initialisation of dynamicfns above */
  dynamicfns[i++].func = (void **)&fptr_findObject;
  dynamicfns[i++].func = (void **)&fptr_typeOfObject;
  dynamicfns[i++].func = (void **)&fptr_getPropertyAsString;
  dynamicfns[i++].func = (void **)&fptr_setPropertyAsString;
  dynamicfns[i++].func = (void **)&fptr_callMethod;
  dynamicfns[i++].func = (void **)&fptr_registerObject;
  dynamicfns[i++].func = (void **)&fptr_registerPropertyDL;
  dynamicfns[i++].func = (void **)&fptr_registerEventHandlerDL;
  dynamicfns[i++].func = (void **)&fptr_registerMethodDL;
  dynamicfns[i++].func = (void **)&fptr_fireEvent;
  dynamicfns[i++].func = (void **)&fptr_getPluginInfo;
  dynamicfns[i++].func = (void **)&fptr_setPluginInfo;
  dynamicfns[i++].func = (void **)&fptr_requestUnload;
  dynamicfns[i++].func = (void **)&fptr_changePage;
  dynamicfns[i++].func = (void **)&fptr_loadXMLFile;
  dynamicfns[i++].func = (void **)&fptr_performAction;
  dynamicfns[i++].func = (void **)&fptr_unregisterObject;
  dynamicfns[i++].func = (void **)&fptr_unregisterEventHandlerDL;
  dynamicfns[i++].func = (void **)&fptr_createWidget;
  dynamicfns[i++].func = (void **)&fptr_createPage;
  dynamicfns[i++].func = (void **)&fptr_cloneWidget;
  dynamicfns[i++].func = (void **)&fptr_deleteWidget;
  dynamicfns[i++].func = (void **)&fptr_deletePage;
  dynamicfns[i++].func = (void **)&fptr_runScript;

  /* Iterate through the functions and resolve each one */
  for(i=0; i < (sizeof dynamicfns / sizeof (struct dynamicfn)); i++) {
    funcptr = resolverfn(dynamicfns[i].name);
    if(!funcptr) {
      fprintf(stderr, "plugin error: resolver function failed to return pointer to %s\n", dynamicfns[i].name);
      return EBERR_NORESOLVE;
    }
    *(dynamicfns[i].func) = funcptr;
  }

  /* Save ID */
  internal_plugin_id = plugin_id;

  /* All went well */
  return EBERR_SUCCESS;
}

void eboxy_clientlib_deinit(void) {
  /* Nothing to do here right now */
}

struct eboxy_version_info eboxy_clientlib_getver(void) {
  /* Return the version of this client library */
  struct eboxy_version_info des;
  des.major = CLIENTLIB_VERSION_MAJOR;
  des.minor = CLIENTLIB_VERSION_MINOR;
  des.subminor = CLIENTLIB_VERSION_SUBMINOR;
  return des;
}

/* The wrapper functions. The signatures of these should be almost identical to the
   definitions found in pluginmanager.h. Note: be careful to have the function call
   the fptr_ and not itself! */

int findObject(const char *object, const char *type) {
  return fptr_findObject(object, type);
}

const char *typeOfObject(const char *object) {
  return fptr_typeOfObject(object);
}

char *getPropertyAsString(const char *object, const char *property) {
  return fptr_getPropertyAsString(object, property);
}

int setPropertyAsString(const char *object, const char *property, const char *value) {
  return fptr_setPropertyAsString(object, property, value);
}

char *callMethod(const char *object, const char *method, int numargs, const char *args[]) {
  return fptr_callMethod(object, method, numargs, args);
}

int registerObject(const char *name) {
  return fptr_registerObject(name, internal_plugin_id);
}

int registerPropertyDL(const char *object, const char *property, const char *getter, const char *setter) {
  return fptr_registerPropertyDL(object, property, internal_plugin_id, getter, setter);
}

int registerEventHandlerDL(const char *object, const char *event, const char *eventfunc) {
  return fptr_registerEventHandlerDL(object, event, internal_plugin_id, eventfunc);
}

int registerMethodDL(const char *object, const char *method, int numargs, const char *methodfunc) {
  return fptr_registerMethodDL(object, method, internal_plugin_id, numargs, methodfunc);
}

int fireEvent(const char *object, const char *event) {
  return fptr_fireEvent(object, event, internal_plugin_id);
}

const struct plugin_info *getPluginInfo(const char *name) {
  return fptr_getPluginInfo(name);
}

void setPluginInfo(const char *namestring, const char *verstring) {
  fptr_setPluginInfo(internal_plugin_id, namestring, verstring);
}

void requestUnload(void) {
  fptr_requestUnload(internal_plugin_id);
}

int changePage(const char *pagename) {
  return fptr_changePage(pagename);
}

int loadXMLFile(const char *filename, const char *pagename) {
  return fptr_loadXMLFile(filename, pagename);
}

int performAction(const char *actionname) {
  return fptr_performAction(actionname);
}

int unregisterObject(const char *name) {
  return fptr_unregisterObject(name, internal_plugin_id);
}

int unregisterEventHandlerDL(const char *object, const char *event) {
  return fptr_unregisterEventHandlerDL(object, event, internal_plugin_id);
}

int createWidget(const char *name, const char *type, const char *templatename) {
  return fptr_createWidget(name, type, templatename);
}

int createPage(const char *name) {
  return fptr_createPage(name);
}

int cloneWidget(const char *original, const char *duplicate) {
  return fptr_cloneWidget(original, duplicate);
}

int deleteWidget(const char *name) {
  return fptr_deleteWidget(name);
}

int deletePage(const char *name) {
  return fptr_deletePage(name);
}

int runScript(const char *code, int flags) {
  return fptr_runScript(code, flags);
}

/* Some extensions to the wrapper functions */

int isPluginLoaded(const char *name) {
  const struct plugin_info *pl_info;
  pl_info = getPluginInfo(name);
  return pl_info != NULL;
}

void callMethodNoReturn(const char *object, const char *method, int numargs, const char *args[]) {
  char *res;
  res = callMethod(object, method, numargs, args);
  if(res)
    free(res);
}


syntax highlighted by Code2HTML, v. 0.9.1