/* This file is part of the KDE project
   Copyright (C) 2003,2005 Jaroslaw Staniek <js@iidea.pl>

   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; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "kexidbconnectionset.h"
#include "kexidbshortcutfile.h"

#include <kdebug.h>
#include <kstandarddirs.h>

#include <tqfile.h>

//! @internal
class KexiDBConnectionSetPrivate
{
public:
	KexiDBConnectionSetPrivate()
	 : dataForFilenames(1009)
	{
		list.setAutoDelete(true);
		maxid=-1;
	}
	KexiDB::ConnectionData::List list;
	TQMap<KexiDB::ConnectionData*, TQString> filenamesForData;
	TQDict<KexiDB::ConnectionData> dataForFilenames;
	int maxid;
};

KexiDBConnectionSet::KexiDBConnectionSet()
: TQObject()
, d(new KexiDBConnectionSetPrivate())
{
}

KexiDBConnectionSet::~KexiDBConnectionSet()
{
	delete d;
}

bool KexiDBConnectionSet::addConnectionData(KexiDB::ConnectionData *data, const TQString& _filename)
{
	if (!data)
		return false;
	if (data->id<0)
		data->id = d->maxid+1;
	//TODO: 	check for id-duplicates
	
	d->maxid = TQMAX(d->maxid,data->id);
//	d->list.append(data);

	TQString filename( _filename );
	bool generateUniqueFilename = filename.isEmpty() 
		|| !filename.isEmpty() && data==d->dataForFilenames[filename];

	if (generateUniqueFilename) {
		TQString dir = KGlobal::dirs()->saveLocation("data", "kexi/connections/", false /*!create*/);
		if (dir.isEmpty())
			return false;
		TQString baseFilename( dir + (data->hostName.isEmpty() ? "localhost" : data->hostName) );
		int i = 0;
		while (KStandardDirs::exists(baseFilename+(i>0 ? TQString::number(i) : TQString())+".kexic"))
			i++;
		if (!KStandardDirs::exists(dir)) {
			//make 'connections' dir and protect it
			if (!KStandardDirs::makeDir(dir, 0700))
				return false;
		}
		filename = baseFilename+(i>0 ? TQString::number(i) : TQString())+".kexic";
	}
	addConnectionDataInternal(data, filename);
	bool result = saveConnectionData(data, data);
	if (!result)
		removeConnectionDataInternal(data);
	return result;
}

void KexiDBConnectionSet::addConnectionDataInternal(KexiDB::ConnectionData *data, const TQString& filename)
{
	d->filenamesForData.insert(data, filename);
	d->dataForFilenames.insert(filename, data);
	d->list.append(data);
}

bool KexiDBConnectionSet::saveConnectionData(KexiDB::ConnectionData *oldData, 
	KexiDB::ConnectionData *newData)
{
	if (!oldData || !newData)
		return false;
	TQMap<KexiDB::ConnectionData*, TQString>::ConstIterator it = d->filenamesForData.find( oldData );
	if (it == d->filenamesForData.constEnd() || it.data().isEmpty())
		return false;
	const TQString filename( it.data() );
	KexiDBConnShortcutFile shortcutFile(filename);
	if (!shortcutFile.saveConnectionData(*newData, newData->savePassword)) // true/*savePassword*/))
		return false;
	if (oldData!=newData)
		*oldData = *newData;
	return true;
}

void KexiDBConnectionSet::removeConnectionDataInternal(KexiDB::ConnectionData *data)
{
	TQMap<KexiDB::ConnectionData*, TQString>::ConstIterator it = d->filenamesForData.find( data );
	const TQString filename( it.data() );
	d->filenamesForData.remove(data);
	d->dataForFilenames.remove(filename);
	d->list.removeRef(data);
}

bool KexiDBConnectionSet::removeConnectionData(KexiDB::ConnectionData *data)
{
	if (!data)
		return false;
	TQMap<KexiDB::ConnectionData*, TQString>::ConstIterator it = d->filenamesForData.find( data );
	if (it == d->filenamesForData.constEnd() || it.data().isEmpty())
		return false;
	TQFile file( it.data() );
	if (!file.remove())
		return false;
	removeConnectionDataInternal(data);
	return true;
}

const KexiDB::ConnectionData::List& KexiDBConnectionSet::list() const
{
	return d->list;
}

void KexiDBConnectionSet::clear()
{
	d->list.clear();
	d->filenamesForData.clear();
	d->dataForFilenames.clear();
}

void KexiDBConnectionSet::load()
{
	clear();
//	TQStringList dirs( KGlobal::dirs()->findDirs("data", "kexi/connections") );
//	kexidbg << dirs << endl;
	TQStringList files( KGlobal::dirs()->findAllResources("data", "kexi/connections/*.kexic") );
//	//also try for capital file extension
//	files += KGlobal::dirs()->findAllResources("data", "kexi/connections/*.KEXIC");
//	kexidbg << files << endl;

	foreach(TQStringList::ConstIterator, it, files) {
		KexiDB::ConnectionData *data = new KexiDB::ConnectionData();
		KexiDBConnShortcutFile shortcutFile( *it );
		if (!shortcutFile.loadConnectionData(*data)) {
			delete data;
			continue;
		}
		addConnectionDataInternal(data, *it);
	}
}

TQString KexiDBConnectionSet::fileNameForConnectionData(KexiDB::ConnectionData *data) const
{
	if (!data)
		return TQString();
	TQMap<KexiDB::ConnectionData*, TQString>::ConstIterator it = d->filenamesForData.find( data );
	return (it == d->filenamesForData.constEnd()) ? TQString() : it.data();
}

KexiDB::ConnectionData* KexiDBConnectionSet::connectionDataForFileName(const TQString& fileName) const
{
	return d->dataForFilenames[fileName];
}