#ifndef	GENPARSE_H
#define	GENPARSE_H

#include <v_lib.h>
#include "rgcache.h"

/*
 * Names can be arbitrary length, but only MAX_ID_LEN are meaningful.
 */
#define	MAX_ID_LEN	128

typedef enum
{
	fg_constant = 1,
	fg_uniform = 2,
	fg_gaussian = 3,
	fg_iterators = 99,
	fg_linear_iterator = 100,
	fg_log10_iterator = 101
} fgen_type;

#define	IS_ITERATOR(gen) \
	((gen)->type > fg_iterators)

/* 
 * TODO1: extend 'iterator' with 'logbase', with selected algorithm
 * the arbitrary base logarithmic interpolation can be easily performed.
 */

/* 
 * TODO2: consider storing all values of iterator in array.
 * Such approach have two advantages:
 *  a) arrays (still unimplemented) can be handled as iterators;
 *  b) both arrays and iterators can be filled with random generators.
 */

typedef struct fgen_s
{
	char		*name;
	fgen_type	type;
	vec_t		last; /* last returned value */
	vboolean	finished; /* iterations complete */
	union
	{
		struct
		{
			rgcache_p rgc;
			vec_t min, max;
		} uniform;
		struct
		{
			rgcache_p rgc; /* must be at the same place */
			vec_t mean, stdev;
		} gaussian;
		struct
		{
			u32_t steps, idx; /* required for bidirectional iterators */
			vec_t from, to, val, delta;
		} ilinear;
		struct
		{
			u32_t steps, idx; /* required for bidirectional iterators */
			vec_t log10from, log10to, log10val, log10delta;
		} ilog10;
	} u;
	vboolean (*next)(struct fgen_s *self,vec_t *ret_val);
	void (*reset)(struct fgen_s *self);
	void (*destroy)(struct fgen_s *self);
} fgen_t, *fgen_p;

#define	GEN_NUM_ITERATIONS(gen)	\
	((gen)->u.ilinear.steps + 1)

/*
 * For all genXXX(), 'name' can be NULL.
 * In such case, as a name will be used:
 *  constant: just string with same number: "%g";
 *  uniform: "uniform_min_%g_max_%g";
 *  gaussian: "gaussian_mean_%g_stdev_%g";
 *  linear: "iterator_linear_from_%g_to_%g_steps_%u";
 *  loglinear: "iterator_loglinear_from_%g_to_%g_steps_%u";
 */
fgen_p V_GLOBAL genConstant(vec_t val, char *name);
fgen_p V_GLOBAL genUniform(vec_t min, vec_t max, char *name);
fgen_p V_GLOBAL genGaussian(vec_t mean, vec_t stdev, char *name);
/*
fgen_p V_GLOBAL genLinear(vec_t from, vec_t to, u32_t steps, char *name);
fgen_p V_GLOBAL genLoglinear(vec_t from, vec_t to, u32_t steps, char *name);
*/

/*
 * Returns number of generators stored in 'store'.
 */
unsigned	V_GLOBAL	parseGenerators(vhandle_t lex,vp_stack_p store);

void	V_GLOBAL	genDestroy(vp_stack_p store);

fgen_p	V_GLOBAL	genFind(vp_stack_p store, char *name);

void	V_GLOBAL	genPrint(vp_stack_p store);

#endif /* GENPARSE_H */
