#include <glib.h>
#include "cfg.h"
#include "edvcontext.h"
#include "edvget.h"
#include "edvcfglist.h"
#include "config.h"


gchar **EDVGetConfigurationParameters(
	edv_context_struct *ctx, gint *total
);

gint EDVGetI(edv_context_struct *ctx, const gchar *parm);
glong EDVGetL(edv_context_struct *ctx, const gchar *parm);
gulong EDVGetUL(edv_context_struct *ctx, const gchar *parm);
gfloat EDVGetF(edv_context_struct *ctx, const gchar *parm);
gdouble EDVGetD(edv_context_struct *ctx, const gchar *parm);
gchar *EDVGetS(edv_context_struct *ctx, const gchar *parm);

gboolean EDVGetVersion(
	edv_context_struct *ctx,
	gint *major, gint *minor, gint *release
);


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)       (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s)       (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)


/*
 *      Returns a list of parameters.
 *
 *      The calling function must deallocate the returned pointer array
 *      and each string.
 */
gchar **EDVGetConfigurationParameters(
	edv_context_struct *ctx, gint *total
)
{
	gint i, t = 0;
	gchar **params = NULL;
	const cfg_item_struct *cfg_ptr;

	if(total != NULL)
	    *total = t;

	if(ctx == NULL)
	    return(params);

	cfg_ptr = ctx->cfg_list;
	if(cfg_ptr == NULL)
	    return(params);

	while(cfg_ptr->parameter != NULL)
	{
	    i = t;
	    t = i + 1;
	    params = (gchar **)g_realloc(params, t * sizeof(gchar *));
	    if(params == NULL)
	    {
		t = 0;
		break;
	    }
	    params[i] = STRDUP(cfg_ptr->parameter);
	    cfg_ptr++;
	}

	if(total != NULL)
	    *total = t;

	return(params);
}

/*
 *      Gets the integer value of the given parameter.
 *
 *	This function does not distinguish error returns.
 */
gint EDVGetI(edv_context_struct *ctx, const gchar *parm)
{
	if((ctx == NULL) || STRISEMPTY(parm))
	    return(0);

	return(CFGItemListGetValueI(
	    ctx->cfg_list, parm
	));
}

/*
 *      Gets the long integer value of the given parameter.
 *
 *      This function does not distinguish error returns.
 */
glong EDVGetL(edv_context_struct *ctx, const gchar *parm)
{
	if((ctx == NULL) || STRISEMPTY(parm))
	    return(0);

	return(CFGItemListGetValueL(
	    ctx->cfg_list, parm
	));
}

/*
 *      Gets the unsigned long integer value of the given parameter.
 *
 *      This function does not distinguish error returns.
 */
gulong EDVGetUL(edv_context_struct *ctx, const gchar *parm)
{
	if((ctx == NULL) || STRISEMPTY(parm))
	    return(0);

	return(CFGItemListGetValueUL(
	    ctx->cfg_list, parm
	));
}

/*
 *      Gets the float value of the given parameter.
 *
 *      This function does not distinguish error returns.
 */
gfloat EDVGetF(edv_context_struct *ctx, const gchar *parm)
{
	if((ctx == NULL) || STRISEMPTY(parm))
	    return(0.0f);

	return(CFGItemListGetValueF(
	    ctx->cfg_list, parm
	));
}

/*
 *      Gets the double value of the given parameter.
 *
 *      This function does not distinguish error returns.
 */
gdouble EDVGetD(edv_context_struct *ctx, const gchar *parm)
{
	if((ctx == NULL) || STRISEMPTY(parm))
	    return(0.0);

	return(CFGItemListGetValueD(
	    ctx->cfg_list, parm
	));
}

/*
 *	Gets the string value of the given parameter.
 *
 *	The returned pointer must not be modified or deallocated.
 *
 *	Can return NULL if the parameter does not exist.
 */
gchar *EDVGetS(edv_context_struct *ctx, const gchar *parm)
{
	if((ctx == NULL) || STRISEMPTY(parm))
	    return(0);

	return(CFGItemListGetValueS(
	    ctx->cfg_list, parm
	));
}

/*
 *	Convience function to return the version of Endeavour found
 *	in the configuration.
 *
 *	Note that this gives the version of Endeavour last recorded
 *	on the configuration file, not always the currently installed
 *	version.
 *
 *	Returns TRUE on success or FALSE on error.
 */
gboolean EDVGetVersion(
	edv_context_struct *ctx,
	gint *major, gint *minor, gint *release
)
{
	const cfg_item_struct *cfg_list;

	if(major != NULL)
	    *major = 0;
	if(minor != NULL)
	    *minor = 0;
	if(release != NULL)
	    *release = 0;

	if(ctx == NULL)
	    return(FALSE);

	cfg_list = ctx->cfg_list;

	if(major != NULL)
	    *major = CFGItemListGetValueI(
		cfg_list, EDV_CFG_PARM_VERSION_MAJOR
	    );
	if(minor != NULL)
	    *minor = CFGItemListGetValueI(
		cfg_list, EDV_CFG_PARM_VERSION_MINOR
	    );
	if(release != NULL)
	    *release = CFGItemListGetValueI(
		cfg_list, EDV_CFG_PARM_VERSION_RELEASE
	    );

	return(TRUE);
}
