/*
 * $Id: prop.h,v 1.6 2005/05/18 18:48:13 cbiere Exp $
 *
 * Copyright (c) 2001-2003, Richard Eckart
 *
 *----------------------------------------------------------------------
 * This file is part of gtk-gnutella.
 *
 *  gtk-gnutella 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.
 *
 *  gtk-gnutella 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 gtk-gnutella; if not, write to the Free Software
 *  Foundation, Inc.:
 *      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *----------------------------------------------------------------------
 */

#ifndef _prop_h_
#define _prop_h_

#include "common.h"
#include "event.h"

#define NO_PROP (0)

/*
 * Use this macro access a property instead of ps->props[prop]. It will
 * hide the offset of the properties, so the property array can be
 * accessed.
 */
#define PROP(ps, p) (ps->props[p-ps->offset])

/*
 * Handle types
 */
typedef guint32 property_t;
typedef guint32 property_set_t;

/*
 * Available property types
 */
typedef enum {
    PROP_TYPE_BOOLEAN,
    PROP_TYPE_GUINT32,
    PROP_TYPE_GUINT64,
    PROP_TYPE_STRING,
    PROP_TYPE_IP,
    PROP_TYPE_STORAGE,
    PROP_TYPE_MULTICHOICE
} prop_type_t;

extern const gchar * const prop_type_str[];

/*
 * Callback signature definition
 */
typedef gboolean (*prop_changed_listener_t) (property_t);

/*
 * Event subscription control call signatures.
 */
typedef void (*prop_add_prop_changed_listener_t)
    (property_t, prop_changed_listener_t, gboolean);
typedef void (*prop_add_prop_changed_listener_full_t)
    (property_t, prop_changed_listener_t, gboolean, enum frequency_type, guint32);
typedef void (*prop_remove_prop_changed_listener_t)
    (property_t, prop_changed_listener_t);

/*
 * Container struct definitions for the different property types
 */
typedef struct prop_def_choice {
    gchar *title;
    guint32 value;
} prop_def_choice_t;


typedef struct prop_def_guint32 {
    guint32 *def;    /* default value */
    guint32 *value;  /* current value */
    guint32 min;     /* minimal value */
    guint32 max;     /* maximal value */
    prop_def_choice_t *choices;
} prop_def_guint32_t;

typedef void (*prop_set_guint32_t)
    (property_t, const guint32 *, size_t, size_t);
typedef guint32 *(*prop_get_guint32_t)
    (property_t, guint32 *, size_t, size_t);


typedef struct prop_def_guint64 {
    guint64 *def;    /* default value */
    guint64 *value;  /* current value */
    guint64 min;     /* minimal value */
    guint64 max;     /* maximal value */
    prop_def_choice_t *choices;
} prop_def_guint64_t;

typedef void (*prop_set_guint64_t)
    (property_t, const guint64 *, size_t, size_t);
typedef guint64 *(*prop_get_guint64_t)
    (property_t, guint64 *, size_t, size_t);


typedef struct prop_def_storage {
    gchar *value;   /* current data */
} prop_def_storage_t;

typedef void (*prop_set_storage_t)(property_t, const gchar *, size_t);
typedef gchar *(*prop_get_storage_t)(property_t, gchar *, size_t);


typedef struct prop_def_string {
    gchar **def;     /* default value */
    gchar **value;   /* current value */
} prop_def_string_t;

typedef void (*prop_set_string_t)(property_t, const gchar *);
typedef gchar *(*prop_get_string_t)(property_t, gchar *, size_t);


typedef struct prop_def_boolean {
    gboolean *def;   /* default value */
    gboolean *value; /* current value */
} prop_def_boolean_t;

typedef void (*prop_set_boolean_t)
    (property_t, const gboolean *, size_t, size_t);
typedef gboolean *(*prop_get_boolean_t)
    (property_t, gboolean *, size_t, size_t);

/*
 * Property definition
 */
typedef struct prop_def {
    gchar *name; /* key used in the config file */
    gchar *desc; /* description of the property */
    prop_type_t type;
    union {
        prop_def_guint32_t  guint32;
        prop_def_guint64_t  guint64;
        prop_def_string_t   string;
        prop_def_boolean_t  boolean;
        prop_def_storage_t  storage;
    } data;
    gboolean save; /* persist across sessions */
    size_t vector_size; /* number of items in array, 1 for non-vector */
    struct event *ev_changed;
} prop_def_t;

/*
 * Property set stub to access property set.
 */
typedef struct prop_set_stub {
    size_t size;
    size_t offset;
    prop_def_t *(*get_def)(property_t);
    property_t (*get_by_name)(const char *);
    gchar *(*to_string)(property_t);
    struct {
        prop_add_prop_changed_listener_t add;
        prop_add_prop_changed_listener_full_t add_full;
        prop_remove_prop_changed_listener_t remove;
    } prop_changed_listener;
    struct {
        prop_get_boolean_t get;
        prop_set_boolean_t set;
    } boolean;
    struct {
        prop_get_guint32_t get;
        prop_set_guint32_t set;
    } guint32;
    struct {
        prop_get_guint64_t get;
        prop_set_guint64_t set;
    } guint64;
    struct {
        prop_get_storage_t get;
        prop_set_storage_t set;
    } storage;
    struct {
        prop_get_string_t get;
        prop_set_string_t set;
    } string;
} prop_set_stub_t;

/*
 * Stub-fetcher signature
 */
typedef prop_set_stub_t *(*prop_set_get_stub_t)(void);

/*
 * Property set definition
 */
typedef struct prop_set {
    gchar *name;       /* name of the property set */
    gchar *desc;       /* description of what the set contains */
    size_t size;      /* number of properties in the set */
    size_t offset;    /* properties start numbering from here */
    prop_def_t *props; /* Pointer to first item in array of prop_def_t */
    GHashTable *byName;/* hashtable to quickly look up props by name */
    time_t mtime;      /* modification time of the associated file */
	gboolean dirty;    /* property set needs flushing to disk */
    prop_set_get_stub_t get_stub;
} prop_set_t;

/*
 * Helpers
 */

prop_def_t *prop_get_def(prop_set_t *, property_t);
void prop_free_def(prop_def_t *);

const gchar *prop_name(prop_set_t *ps, property_t prop);
const gchar *prop_description(prop_set_t *ps, property_t prop);

void prop_add_prop_changed_listener(
    prop_set_t *, property_t, prop_changed_listener_t, gboolean);
void prop_add_prop_changed_listener_full(
    prop_set_t *, property_t, prop_changed_listener_t, gboolean,
    enum frequency_type, guint32);
void prop_remove_prop_changed_listener(
    prop_set_t *, property_t, prop_changed_listener_t);

void prop_save_to_file_if_dirty(
    prop_set_t *ps, const gchar *dir, const gchar *filename);
void prop_save_to_file(
    prop_set_t *ps, const gchar *dir, const gchar *filename);
void prop_load_from_file(
    prop_set_t *ps, const gchar *dir, const gchar *filename);

/*
 * get/set functions
 */
void prop_set_boolean(
    prop_set_t *, property_t, const gboolean *, size_t, size_t);
gboolean *prop_get_boolean(
    prop_set_t *, property_t, gboolean *, size_t, size_t);

void prop_set_string(prop_set_t *, property_t, const gchar *);
gchar *prop_get_string(prop_set_t *, property_t, gchar *, size_t);

void prop_set_guint32(
    prop_set_t *, property_t, const guint32 *, size_t, size_t);
guint32 *prop_get_guint32(
    prop_set_t *, property_t, guint32 *, size_t, size_t);

void prop_set_guint64(
    prop_set_t *, property_t, const guint64 *, size_t, size_t);
guint64 *prop_get_guint64(
    prop_set_t *, property_t, guint64 *, size_t, size_t);

void prop_set_storage(prop_set_t *, property_t, const gchar *, size_t);
gchar *prop_get_storage(prop_set_t *, property_t, gchar *, size_t);

const gchar *prop_to_string(prop_set_t *ps, property_t prop);
property_t prop_get_by_name(prop_set_t *ps, const char *name);
GSList *prop_get_by_regex(prop_set_t *ps, const gchar *pattern, gint *error);
void prop_set_from_string(prop_set_t *ps, property_t prop, const gchar *val,
	gboolean saved_only);

#endif /* _prop_h_ */
/* vi: set ts=4 sw=4 cindent: */
