/*
 * newssource.cpp
 *
 * Copyright (c) 2000 Frerich Raabe <raabe@kde.org>
 *
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include "newssource.h"

#include <kdebug.h>
#include <kconfig.h>
#include <kglobal.h>
#include <kio/job.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kprocess.h>
#include <kstddirs.h>
#include <kcharsets.h>

#include <qdom.h>
#include <qregexp.h>

Article::Article(const QString &headline, const KURL &address, bool read)
{
	_headline = headline;
	_address = address;
	_read = read;
}

Article::Article(const Article *a)
{
	_headline = a->headline();
	_address = a->address();
	_read = a->read();
}

void Article::open()
{
	KProcess p;
	p << KGlobal::dirs()->findResource("exe", "konqueror") << _address.url();
	p.start(KProcess::DontCare);
	_read = true;
}

NewsSource::NewsSource(const QString &sourceFile, const QString &name): QObject(0, 0)
{
	_name = name;
	_sourceFile = sourceFile;
	_maxArticles = 10;
	_article.setAutoDelete(true);
}

NewsSource::NewsSource(KConfig *config, const QString &group)
{
	load(config, group);
	_article.setAutoDelete(true);
}

void NewsSource::load(KConfig *config, const QString &group)
{
	config->setGroup(group);

	_name = config->readEntry("Name");
	_sourceFile = config->readEntry("Address");
	_maxArticles = config->readNumEntry("Max articles", 10);
}

void NewsSource::retrieveNews(bool customNames, uint id)
{
	_customNames = customNames;
	_updateId = id;

	KIO::Job *job = KIO::get(_sourceFile, true, false);
	connect(job,
			SIGNAL(data(KIO::Job *, const QByteArray &)),
			SLOT(downloadData(KIO::Job *, const QByteArray &)));
	connect(job, SIGNAL(result(KIO::Job *)), SLOT(downloadResult(KIO::Job *)));
}

void NewsSource::downloadData(KIO::Job *, const QByteArray &data)
{
	_rdfData += data;
}

void NewsSource::downloadResult(KIO::Job *job)
{
	if (!job->error()) {
		QDomDocument rdfDoc("RDF");

		_rdfData.replace(QRegExp("&"), "&amp;");
		if (rdfDoc.setContent(_rdfData)) {

			if (!_customNames)
				_name = rdfDoc.documentElement().firstChild().namedItem("title").toElement().text();

			QDomNodeList items = rdfDoc.elementsByTagName("item");
			QList<Article> _newArticle;
			for (uint i = 0; i < items.count(); i++) {
				QDomNode itemNode = items.item(i);
				QString headline = itemNode.namedItem("title").toElement().text().replace(QRegExp("&amp;"), "&");
				QString address = itemNode.namedItem("link").toElement().text().replace(QRegExp("&amp;"), "&");
				for (int p = headline.find("&"); p >= 0; p = headline.find("&", p)) {
					int q = headline.find(";", p++);
					if (q != -1)
					  headline.replace(p - 1, q - p + 2, KGlobal::charsets()->fromEntity(headline.mid(p, q - p)));
				}
				if (_newArticle.count() < _maxArticles)
					_newArticle.append(new Article(headline, address));
			}

			if (_article.count() > 0 && _newArticle.count() > 0)
			for (Article *oldArticle = _article.first(); oldArticle != 0; oldArticle = _article.next()) {
				bool inList = false;
				for (Article *newArticle = _newArticle.first(); newArticle != 0; newArticle = _newArticle.next())
					if (newArticle->headline() == oldArticle->headline())
						inList = true;
				if (!inList && _newArticle.count() < _maxArticles)
					_newArticle.append(new Article(oldArticle));
			}
					  
			for (Article *oldArticle = _article.first(); oldArticle != 0; oldArticle = _article.next())
				for (Article *newArticle = _newArticle.first(); newArticle != 0; newArticle = _newArticle.next())
					if (oldArticle->headline() == newArticle->headline())
						newArticle->setRead(oldArticle->read());
			
			_article.clear();
			_article = _newArticle;
			emit newNewsAvailable(this, _updateId, !(_article == _newArticle));

		} else
			emit invalidInput(_name);
	}

  _rdfData = QString::null;
}

Article *NewsSource::article(const QString &headline)
{
	Article *article = 0;

	for (article = _article.first(); article != 0; article = _article.next())
		if (article->headline() == headline)
			return article;

	return article;
}

#include "newssource.moc"
