/* 
 * Copyright (C) 2003 Tim Martin
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <errno.h>

#include "utils.h"
#include "senkenconfig.h"

struct configlist {
    char *key;
    char *value;
};

static struct configlist *configlist;
static int nconfiglist;
static int alloced = 0;

#define CONFIGLISTGROWSIZE 10 /* 100 */

extern int
config_init(const char *filename)
{
    FILE *infile;
    int lineno = 0;
    char buf[4096];
    char *p, *key;

    nconfiglist = 0;

    infile = fopen(filename, "r");
    if (!infile) {
	return ENOENT;
    }
    
    while (fgets(buf, sizeof(buf), infile)) {
	lineno++;

	/* remove newline */
	if (buf[strlen(buf)-1] == '\n') {
	    buf[strlen(buf)-1] = '\0';
	} else {
	    continue;
	}
	/* skip past beginiing spaces */
	for (p = buf; *p && isspace((int) *p); p++);
	if (!*p || *p == '#') continue;

	/* read key */
	key = p;
	while (*p && (isalnum((int) *p) || *p == '-' || *p == '_')) {
	    if (isupper((int) *p)) *p = tolower(*p);
	    p++;
	}
	if (*p != ':') {
	  return -1;
	}
	*p++ = '\0';

	/* skip past spaces */
	while (*p && isspace((int) *p)) p++;
	
	if (!*p) {
	    /* empty value */
	    continue;
	}

	if (nconfiglist == alloced) {
	    alloced += CONFIGLISTGROWSIZE;
	    configlist=realloc((char *)configlist, alloced*sizeof(struct configlist));
	    if (configlist==NULL) return -1;
	}

	/*
	 * Set values
	 */
	configlist[nconfiglist].key = strdup(key);
	configlist[nconfiglist].value = strdup(p);

	nconfiglist++;
    }
    fclose(infile);

    return 0;
}

extern const char *
config_getstring(const char *key,const char *def)
{
    int opt;

    for (opt = 0; opt < nconfiglist; opt++) {
	if (!strcasecmp(key, configlist[opt].key))
	  return configlist[opt].value;
    }
    return def;
}

extern int
config_getint(const char *key,int def)
{
    const char *val = config_getstring(key, (char *)0);

    if (!val) return def;
    if (!isdigit((int) *val) && (*val != '-' || !isdigit((int) val[1]))) return def;
    return atoi(val);
}

extern int 
config_getfunction_evaluate(const char *key, func_getvariable_cb *getvar_cb, 
			    void *getvar_rock, int def)
{
    const char *val = config_getstring(key, (char *)0);
    func_t *func;

    if (!val) return def;

    func = function_parse_string(strdup((char *)val));
    if (!func) {
	printf(_("Error parsing %s's value %s\n"), key, val);
	return def;
    }

    return function_evaluate(func, getvar_cb, getvar_rock);
}

extern int
config_getswitch(const char *key,int def)
{
    const char *val = config_getstring(key, (char *)0);

    if (!val) return def;

    if (*val == '0' || *val == 'n' ||
	(*val == 'o' && val[1] == 'f') || *val == 'f') {
	return 0;
    }
    else if (*val == '1' || *val == 'y' ||
	     (*val == 'o' && val[1] == 'n') || *val == 't') {
	return 1;
    }
    return def;
}

