/*
 * widgetlib.h
 *
 * UI toolkit for C modelled after Tk
 *
 * HEADER FILE
 *
 * Author: Dario Rodriguez antartica@whereismybit.com
 * Please see the file LICENSE.txt in the source's root directory.
 */

#ifndef WIDGETLIB_H
#define WIDGETLIB_H

#include <stdarg.h>

#include "SDL.h"
#include "SDL_rwops.h"
#include "SDL_image.h"
#include "SDL_ttf.h"

/* widget names */
#define WI_LABEL "label"
#define WI_FRAME "frame"
#define WI_IMAGE "image"

/* debug info */
#ifndef _F
#define _F __FILE__
#endif
#ifndef _L
#define _L __LINE__
#endif

/* structs */
typedef struct xywh_t {
        int x;
        int y;
        int w;
        int h;
} xywh_t;

typedef struct wh_t {
        int w;
        int h;
} wh_t;

typedef enum wianchor_t {
        anchor_center=0,
        anchor_nw,
        anchor_n,
        anchor_ne,
        anchor_w,
        anchor_e,
        anchor_sw,
        anchor_s,
        anchor_se,
} wianchor_t;

typedef enum wifill_t {
        fill_none=0,
        fill_x,
        fill_y,
        fill_both,
} wifill_t;

typedef struct wiplace_t {
        int enabled;
        xywh_t xywh;
        int flag_whfromparent;
} wiplace_t;

typedef struct wiconf_t {
        char *name;
        int sizevalue;
        int usedvalue;
        char *value;
        int flag_var; /* value contains autovarname */
        int flag_image; /* images are also vars (flag_var should also be set) */
        wh_t image;
        void (*callback)(void *wi, char *toplevelname, char *widgetname, char *confname);
} wiconf_t;

typedef struct widget_t {
        int sizename;
        int usedname;
        char *name;
        char *classname;
        int sizeclassdata;
        char *classdata;
        wiplace_t place;
        xywh_t box;
        xywh_t padipadbox;
        xywh_t displaybox;
        int pad_left;
        int pad_right;
        int pad_top;
        int pad_bottom;
        int ipad_left;
        int ipad_right;
        int ipad_top;
        int ipad_bottom;
        wianchor_t anchor;
        wifill_t fill;
        int sizeconfs;
        int usedconfs;
        wiconf_t **confs;
        SDL_Surface *surface;
        SDL_Texture *texture;
        int dirty;
} widget_t;

typedef struct witoplevel_t {
        char *toplevelname;
        widget_t rootwidget;
        int sizewidgets;
        int usedwidgets;
        widget_t **widgets;
        int sizebufwidgets;
        int usedbufwidgets;
        widget_t **bufwidgets;
        int sizeconfs;
        int usedconfs;
        wiconf_t **confs;
        SDL_Window *win;
        SDL_Renderer *renderer;
        int dirty;
} witoplevel_t;

typedef struct wialias_t {
        char *alias;
        int sizepath;
        int usedpath;
        char *path;
} wialias_t;

typedef struct wivar_t {
        char *autovarname;
        int sizevardata;
        int usedvardata;
        char *vardata;
} wivar_t;

typedef enum wiclassoptype_t {
        classop_initclass=0,
        classop_freeclass,
        classop_initinstance,
        classop_freeinstance,
        classop_render,
} wiclassoptype_t;

typedef struct wiclassop_t {
        wiclassoptype_t op;
} wiclassop_t;

typedef struct wiclass_t {
        char *classname;
        int sizeclassglobaldata;
        char *classglobaldata;
        int (*classcallback)(void *wi, struct wiclass_t *cl, widget_t *widget, wiclassop_t *op);
} wiclass_t;

typedef struct wifontinstance_t {
        int size;
        TTF_Font *font;
} wifontinstance_t;

typedef struct wifont_t {
        char *name;
        int sizedata;
        char *data;
        SDL_RWops *rwops;
        int sizefontinstances;
        int usedfontinstances;
        wifontinstance_t *fontinstances;
} wifont_t;

typedef struct wi_t {
        int sizeclasses;
        int usedclasses;
        wiclass_t *classes;
        int sizetoplevels;
        int usedltoplevels;
        witoplevel_t *toplevels;
        int currenttoplevel;
        int sizealiases;
        int usedaliases;
        wialias_t **aliases;
        int sizevars;
        int usedvars;
        wivar_t **vars;
        int sizefonts;
        int usedfonts;
        wifont_t *fonts;
} wi_t;

wi_t *wi_init(void);
void wi_free(wi_t *wi);

int wi_class_register(wi_t *wi, char *classname, int (*classcallback)(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op));
int wi_class_unregister(wi_t *wi, char *classname);

int wi_toplevel_set(wi_t *wi, char *name);
int wi_toplevel_destroy(wi_t *wi, char *name);

#ifndef __GNUC__
char *wi_add(wi_t *wi, char *debugfile, int debugline, char *class, char *path, char *format,...);
char *wi_config(wi_t *wi, char *debugfile, int debugline, char *path, char *format,...);
int wi_pack(wi_t *wi, char *debugfile, int debugline, char *path, char *format,...);
#else
  char *wi_add(wi_t *wi, char *debugfile, int debugline, char *class, char *path, char *format,...) __attribute__ ((format (printf,6,7)));
  char *wi_config(wi_t *wi, char *debugfile, int debugline, char *path, char *format,...) __attribute__ ((format (printf,5,6)));
  int wi_pack(wi_t *wi, char *debugfile, int debugline, char *path, char *format,...) __attribute__ ((format (printf,5,6)));
#endif
int wi_destroy(wi_t *wi, char *path);

int wi_alias_set(wi_t *wi, char *alias, char *path);
int wi_alias_unset(wi_t *wi, char *alias);

int wi_tree_move(wi_t *wi, char *path, char *newparent);

int wi_var_updated(wi_t *wi, char *vardata, int sizevardata);
int wi_var_destroy(wi_t *wi, char *vardata, int sizevardata);

int wi_font_load(wi_t *wi, char *filename, char *fontname);

/* default widgets */
int wi_classcallback_frame(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op);
int wi_classcallback_label(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op);
int wi_classcallback_image(void *wi, wiclass_t *cl, widget_t *widget, wiclassop_t *op);
#endif