#include <configfile.h>
#include <unistd.h>
#include <stdio.h>

#include <iostream>

using namespace std;

ConfigFile::ConfigFile() : dirty(false), opened(false)
{
}

ConfigFile::~ConfigFile()
{
    Close();
}

ConfigEntry* ConfigFile::Find(const string& appname, const string& valname)
{
    if (opened)
    {
	for (unsigned i = 0; i < entries.size(); i++)
	    if (entries[i].appname == appname
		&& entries[i].valname == valname)
		return &entries[i];
    }
    return 0;
}

void ConfigFile::Open(const string& fn)
{
    if (opened)
	if (filename == fn)
	    return;
	else
	    Close();

    char* pathname;
#ifndef WIN32
    passwd* pwent;
    pwent=getpwuid(getuid());
    pathname=new char[strlen(pwent->pw_dir)+fn.size()+20];
    strcpy(pathname, pwent->pw_dir);
#else
    pathname=new char[256 + fn.size() + 20];
    GetWindowsDirectory(pathname, 256);
#endif
    strcat(pathname, "/");
    strcat(pathname, fn.c_str());
    FILE* f=fopen(pathname, "rb");
    delete pathname;

    filename = fn;
    opened = true;
    dirty = false;
    if(!f)
	return;

    char appname[256], valname[256], type[16];
    int len;

    while (!feof(f))
    {

	fscanf(f, "%s %s = %d [ %s ] ", appname, valname, &len, type);
	ConfigEntry e;
	e.appname=appname;
	e.valname=valname;
	e.length=len;

	if (strncmp(type, "Int", 16)==0)
	{
	    fscanf(f, "%X\n", &e.i);
	    e.type=ConfigEntry::Int;
	    entries.push_back(e);
	}
	else if (strncmp(type, "Float", 16)==0)
	{
	    fscanf(f, "%f\n", &e.f);
	    e.type=ConfigEntry::Float;
	    entries.push_back(e);
	}
	else if (strncmp(type, "Binary", 16)==0)
	{
	    e.b=new char[e.length+1];
	    e.b[e.length]=0;
	    fread(e.b, e.length, 1, f);
	    fscanf(f, "\n");
	    e.type=ConfigEntry::Binary;
	    entries.push_back(e);
	}
	else //junk
	    while (!feof(f))
	    {
		char c=0;
		fread(&c,1,1,f);
		if (c=='\n')
		    break;
	    }
    }
}

void ConfigFile::Close()
{
    if (!opened || !dirty)
	return;

    opened=false;
    char* pathname;
#ifndef WIN32
    passwd* pwent;
    pwent = getpwuid(getuid());
    pathname = new char[strlen(pwent->pw_dir)+filename.size()+20];
    strcpy(pathname, pwent->pw_dir);
#else
    pathname = new char[256 + filename.size() + 20];
    GetWindowsDirectory(pathname, 256);
#endif
    strcat(pathname, "/");
    strcat(pathname, filename.c_str());

    // FIXME - do backup copy before overwrite!  (rename)
    FILE* f = fopen(pathname, "wb");
    delete pathname;
    if (!f)
	return;

    for (unsigned i=0; i<entries.size(); i++)
    {
	fprintf(f, "%s %s = %d [ ", entries[i].appname.c_str(), entries[i].valname.c_str(), entries[i].length);
	switch(entries[i].type)
	{
	case ConfigEntry::Int:
	    fprintf(f, "Int ] %X\n", entries[i].i);
	    break;
	case ConfigEntry::Float:
	    fprintf(f, "Float ] %f\n", entries[i].f);
	    break;
	case ConfigEntry::Binary:
	    fprintf(f, "Binary ] ");
	    fwrite(entries[i].b, entries[i].length, 1, f);
	    fprintf(f, "\n");
	    break;
	}
    }

    fclose(f);
}

void ConfigFile::push_back(const ConfigEntry& e)
{
    dirty = true;
    entries.push_back(e);
}
