/*
 *  Copyright 1994-2022 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou 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.
 *
 *  lebiniou 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 lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __BINIOU_PLUGIN_H
#define __BINIOU_PLUGIN_H

#include <jansson.h>
#include "options.h"

#define PLUGIN_PARAMETER_CHANGED 2

enum PluginType { PL_INPUT, PL_MAIN, PL_OUTPUT };

struct Context_s;

typedef struct Plugin_s {
  void   *handle;   /* .so handle */

  uint32_t version; /* version to increase when exposed parameters change */
  uint32_t *options;
  enum LayerMode *mode;

  char   *name;
  gchar  *file;     /* to unload/reload */
  char   *dname;    /* display name */
  char   *desc;     /* plugin description */
  char   *html_description; // HTML description for use in the VUI

  pthread_t thread;

  uint32_t calls;     /* number of times this plugin was run */
  uint8_t selected_param;

  /* TODO a struct callbacks */
  /* callbacks */
  int8_t  (*create)(struct Context_s *);        /* constructor: returns 0 if plugin failed to initialize */
  void    (*destroy)(struct Context_s *);       /* destructor */
  int8_t  (*check_version)(uint32_t version);	/* returns 0 if plugin is not compatible with version */

  void    (*run)(struct Context_s *);	        /* run function */
  json_t *(*parameters)(struct Context_s *, const json_t *, const uint8_t); /* parameters managment */
  void *  (*jthread)(void *);                   /* joinable thread */

  void    (*on_switch_on)(struct Context_s *);  /* switching on */
  void    (*on_switch_off)(struct Context_s *); /* switching off */

  /* Output plugin stuff */
  void    (*fullscreen)(const int);
  void    (*switch_cursor)(void);
  json_t *(*command)(struct Context_s *, const json_t *);
} Plugin_t;

Plugin_t *Plugin_new(const char *, const char *, const enum PluginType);
uint32_t Plugin_delete(Plugin_t *);
void Plugin_reload(Plugin_t *);

int8_t Plugin_init(Plugin_t *);

// Plugin parameters
uint8_t plugin_parameter_number(json_t *);

void plugin_parameters_add_boolean(json_t *params, const char *, const int, const char *);
void plugin_parameters_add_int(json_t *, const char *, const int, const int, const int, const int, const char *);
void plugin_parameters_add_double(json_t *params, const char *, const double, const double, const double, const double, const char *);
void plugin_parameters_add_playlist(json_t *params, const char *, json_t *, const char *);
void plugin_parameters_add_string_list(json_t *, const char *, const uint32_t, const char **elems, const uint32_t, const int, const char *);

uint8_t plugin_parameter_parse_boolean(const json_t *, const char *, int *);
uint8_t plugin_parameter_parse_int(const json_t *, const char *, int *);
uint8_t plugin_parameter_parse_int_range(const json_t *, const char *, int *);
uint8_t plugin_parameter_parse_double(const json_t *, const char *, double *);
uint8_t plugin_parameter_parse_double_range(const json_t *, const char *, double *);
uint8_t plugin_parameter_parse_playlist(const json_t *, const char *, json_t **);
uint8_t plugin_parameter_find_string_in_list(const json_t *, const char *, int *);
uint8_t plugin_parameter_parse_string_list_as_int_range(const json_t *, const char *, const uint32_t nb_elems, const char **, int *);
uint8_t plugin_parameter_parse_string(const json_t *, const char *, char **);

json_t *plugin_parameter_change(struct Context_s *, const float);
json_t *plugin_parameter_change_selected(struct Context_s *, const float);
json_t *plugin_parameter_set_selected_from_checkbox(struct Context_s *, const int);
json_t *plugin_parameter_set_selected_from_playlist(struct Context_s *, const json_t *);
json_t *plugin_parameter_set_selected_from_select(struct Context_s *, const char *);
json_t *plugin_parameter_set_selected_from_slider(struct Context_s *, const int);

json_t *plugin_parameters_to_saved_parameters(json_t *in);

#endif /* __BINIOU_PLUGIN_H */
