#include <glib.h>
#include "cfg.h"
#include "edv_context.h"
#include "edv_get.h"
#include "edv_cfg_list.h"
#include "config.h"


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

gboolean EDVGetB(edv_context_struct *ctx, const gchar *parm);
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);
const 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)


/*
 *	Gets the configuration parameters list.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The total specifies the return value for the number of
 *	configuration parameters.
 *
 *	Returns a dynamically allocated list of configuration
 *	parameters. The calling function must delete 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 boolean value of the configuration parameter.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The parm specifies the configuration parameter.
 */
gboolean EDVGetB(edv_context_struct *ctx, const gchar *parm)
{
        if((ctx == NULL) || STRISEMPTY(parm))
            return(FALSE);

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

/*
 *	Gets the integer value of the configuration parameter.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The parm specifies the configuration parameter.
 */
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 configuration parameter.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The parm specifies the configuration parameter.
 */
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 configuration
 *	parameter.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The parm specifies the configuration parameter.
 */
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 configuration parameter.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The parm specifies the configuration parameter.
 */
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 configuration parameter.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The parm specifies the configuration parameter.
 */
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 configuration parameter.
 *
 *	The ctx specifies the Endeavour 2 Context.
 *
 *	The parm specifies the configuration parameter.
 *
 *	The returned pointer must not be modified or deleted. Can
 *	return NULL if the parameter does not exist.
 */
const gchar *EDVGetS(edv_context_struct *ctx, const gchar *parm)
{
	if((ctx == NULL) || STRISEMPTY(parm))
	    return(NULL);

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


/*
 *	Gets the version of Endeavour 2 from the configuration.
 *
 *	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);
}
