/***************************************************************************
 *   Copyright (C) 2004 by EVER Sp. z o.o.                                 *
 *                                                                         *
 *   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 <iostream>
#include <cstdlib>
#include <list>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include "conf.h"

using namespace std;

int CConf::parse_config()
{
	FILE *fc = fopen(lpConfFile, "r");
	if (!fc) {
		iErrorCode = CONF_ERR_FILEOPEN;
		return CONF_FAILURE;
	} else {
		char *line;
		
		while (!feof(fc)) {
			if (read_line(fc, &line) != CONF_SUCCESS) {
				fclose(fc);
				return CONF_FAILURE;
			}
			if (line!=NULL) {
				parse_line(line);
				free(line); //because of read_line allocation (strdup)
			}
		}
		fclose(fc);
	}
	return CONF_SUCCESS;
}

int CConf::read_line(FILE *lpf, char **lb)
{
	// read from file and return in the spec. buff. all data up to the first line break
	const int ilen = 1024;
	char *buf = (char*)new char[ilen];
	if (buf==NULL) {
		iErrorCode=CONF_ERR_MEMALLOC;
		return CONF_FAILURE;
	}
	memset(buf, 0, sizeof(char)*ilen);

	int icnt = fread(buf, 1, ilen, lpf);
	if (icnt>0) {
		char *stok = strtok(buf, "\n");
		if (stok!=NULL) {
			*lb = (char *)strdup(stok);
			if (*lb!=NULL) {
				int ioffset=((stok-buf));
				fseek(lpf, ftell(lpf)-(icnt-strlen(*lb)-ioffset-1), SEEK_SET);
				delete [] buf;
				return CONF_SUCCESS;
			}
		} else {
			*lb=NULL;
			delete [] buf;
			return CONF_SUCCESS;
		}
	} else {
		*lb=NULL;
		delete [] buf;
		return CONF_SUCCESS;
	}
	return CONF_FAILURE;
}

int CConf::parse_line(char *line)
{
	if (line==NULL)
		return CONF_FAILURE;

	char *tok, *lnbuf=strdup(line);
	cleanup_text(&lnbuf);
	if (is_comment(lnbuf)==false) {
		CItem *lpi = new CItem;
		if (lpi!=NULL) {
			if ((tok = strtok(lnbuf, "="))!=NULL) {
				lpi->name = strdup(tok);
				cleanup_text(&lpi->name);
				if ((tok = strtok(NULL, "="))!=NULL) {
					lpi->value = strdup(tok);
					cleanup_text(&lpi->value);
				} else
					lpi->value = NULL;
				pci.push_back(lpi);
			}
		}
	}
	free(lnbuf);
	
	return CONF_SUCCESS;
}

void CConf::cleanup_text(char **line)
{
	if ((*line)!=NULL) {
		int ispc, icnt=strlen(*line);
		
		char *ln=*line;
		// count no. of leading spaces to remove
		for (ispc=0; ispc<icnt; ispc++) {
			if (ln[ispc]!=' ')
				break;
		}
		if (ispc) {
			// shift string to the left
			for (int i=0; i<(icnt-ispc); i++) {
				ln[i]=ln[i+ispc];
			}
			ln[icnt-ispc-1]='\0';
		}
	}
}

// check if the line is commented out by # or ; or '.
bool CConf::is_comment(char *line)
{
	if (line!=NULL)
		if ((*line=='#') || (*line==';'))
			return true;
	return false;
}

char *CConf::geterrordesc()
{
	switch(iErrorCode) 
	{
	case (-100): return CONF_ERR_FILEOPEN_DESC;
	case (-101): return CONF_ERR_NOTHINGTOPARSE_DESC;
	case (-102): return CONF_ERR_INVALIDFORMAT_DESC;
	case (-103): return CONF_ERR_MEMALLOC_DESC;
	case (-104): return CONF_ERR_LINETOOLONG_DESC;
	case (-105): return CONF_ERR_INVALIDDATA_DESC;
	default: return CONF_ERR_GENERIC_DESC;
	}
}

char *CConf::getcfgitemvalue(char *name)
{
 	list<CItem*>::iterator it;
	for (it=pci.begin(); it!=pci.end(); it++) {
		if (!strcasecmp(name, ((CItem*)*it)->name))
			return ((CItem *)*it)->value;
	}
	return "";
}

