/* $Id: addrbook.cpp,v 1.6 2004/01/02 03:54:01 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of a library used by the Archimedes email client     * 
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   This program is free software; you can redistribute it and/or modify      *
 *   it under the terms of the GNU Library 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 Library General Public License for more details.                      *
 *                                                                             *
 *   You should have received a copy of the GNU Library 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 <string>
#include <list>
#include <new>

using namespace std;

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

#include "fmail.h"
#include "umail.h"
#include "addrbook.h"

/**************
 * AddressBook
 **************/

AddressBook::AddressBook(const AddressBook &addrbook)
{

	name = "";
	flags = 0;
	*this = addrbook;
}

AddressBook::~AddressBook()
{

	clearbook();
}

void
AddressBook::AddEntry(AddressBookEntry *entry)
{
    iterator p;

    for (p = begin(); p != end() && AddressBookEntry::compare(entry, *p) > 0; p++);

    insert(p, entry);
}

bool
AddressBook::DeleteEntry(AddressBookEntry *entry)
{
    iterator p;

    /* Requires pointer match */
    for (p = begin(); p != end(); p++)
		if (*p == entry) {
			delete entry;
			erase(p);
			return true;
		}
    return false;
}

AddressBookEntry *
AddressBook::FindEntry(const char *addr)
{
    iterator p;

    if (addr == NULL)
		return NULL;

    for (p = begin(); p != end(); p++)
		if ((*p)->Match(addr))
			return *p;

    return NULL;			
}

AddressBookEntry *
AddressBook::FindEntry(struct _mail_addr *addr)
{
    iterator p;

    for (p = begin(); p != end(); p++)
		if ((*p)->Match(addr))
			return *p;
    return NULL;
}

bool
AddressBook::Load(const char *configdir)
{
    char fname[PATH_MAX];
    FILE *fp;

    /* clear book first */
    clearbook();

    snprintf(fname, sizeof(fname), "%s/.xfbook.%s", configdir, name.c_str());
    if ((fp = fopen(fname, "r")) == NULL) {
		if (name == "default") {
			snprintf(fname, sizeof(fname), "%s/.xfbook", configdir);
			if ((fp = fopen(fname, "r")) == NULL)
				return false;
		} else
			return false;
    }

    return load(fp);
}

bool
AddressBook::LoadFromFile(const char *fname)
{
    FILE *fp;

    if ((fp = fopen(fname, "r")) == NULL)
		return false;

    return load(fp);
}

bool
AddressBook::Save(const char *configdir)
{
    char fname[PATH_MAX], fnametemp[PATH_MAX];
    bool ret;
    FILE *fp;

    snprintf(fnametemp, sizeof(fnametemp), "%s/.__save_xfbook.%s",
		configdir, name.c_str());
    snprintf(fname, sizeof(fname), "%s/.xfbook.%s", configdir, name.c_str());

    if ((fp = fopen(fnametemp, "w")) == NULL) {
		display_msg(MSG_LOG, __func__, "Can not open\n%s", fnametemp);
		return false;
    }

    ret = save(fp);

    if (ret) {
#ifdef __EMX__	/* Under OS/2 the file will not be deleted during rename() */
		if(access(fname, F_OK) == 0) {
			if(unlink(fname) != 0) {
				display_msg(MSG_LOG, __func__, "delete %s before moving",
					fname);
			}
		}
#endif
		if(rename(fnametemp, fname) == -1) {
			display_msg(MSG_LOG, __func__, "rename failed");
			unlink(fnametemp);
			return false;
		}
    } else
		unlink(fnametemp);

    return ret;
}

bool
AddressBook::SaveToFile(const char *fname)
{
    FILE *fp;

    if ((fp = fopen(fname, "w")) == NULL)
		return false;

    return save(fp);
}

bool
AddressBook::operator<(const AddressBook &addrbook)
{

    return name < addrbook.name;
}

bool
AddressBook::operator>(const AddressBook &addrbook)
{

    return name > addrbook.name;
}

bool
AddressBook::operator==(const AddressBook &addrbook)
{

    return name == addrbook.name;
}

/*
bool
operator<(const AddressBook *addrbook1, const AddressBook *addrbook2)
{

    return addrbook1->name < addrbook2->name;
}

bool
operator>(const AddressBook *addrbook1, const AddressBook *addrbook2)
{

    return addrbook1->name > addrbook2->name;
}

bool
operator==(const AddressBook *addrbook1, const AddressBook *addrbook2)
{

    return addrbook1->name == addrbook2->name;
}
*/

AddressBook &
AddressBook::operator=(const AddressBook &addrbook)
{
    const_iterator p;

    /* self-assignment */
    if (this == &addrbook)
		return *this;

    clearbook();
    name = addrbook.name;
    flags = addrbook.flags;
    for (p = addrbook.begin(); p != addrbook.end(); p++);
    push_back(new AddressBookEntry(*(*p)));

    return *this;
}

void
AddressBook::clearbook()
{
    iterator p;

    flags = 0;
    for (p = begin(); size() > 0;) {
		delete *p;
		p = erase(p);
    }
}		

bool
AddressBook::load(FILE *fp)
{
    AddressBookEntry *entry;
    int fline, ret;

    //	flags = ABOOK_LOCAL;
    flags = 0;
    fline = 0;
    entry = new AddressBookEntry();
    while ((ret = entry->Read(fp)) != -1) {
		if (ret > 0) {
			delete entry;
			display_msg(MSG_LOG, __func__, "Invalid address book format");
			return false;
		}

		fline++;
		AddEntry(entry);
		entry = new AddressBookEntry();
    }

    delete entry;

    /* Didn't hit EOF, must have been a read error */
    if (!feof(fp)) {
		fclose(fp);
		return false;
    }

    fclose(fp);
    return true;
}

bool
AddressBook::save(FILE *fp)
{
    iterator p;

    for (p = begin(); p != end(); p++)
		if (!(*p)->Write(fp)) {
			fclose(fp);
			return false;
		}

    fclose(fp);
    return true;
}

