/*
 * xmlnewsaccess.cpp
 *
 * Copyright (c) 2001 Frerich Raabe <raabe@kde.org>
 *
 * 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. For licensing and distribution details, check the
 * accompanying file 'COPYING'.
 */
#include "xmlnewsaccess.h"

#include <kcharsets.h>
#include <kdebug.h>
#include <tdeglobal.h>

#include <tqbuffer.h>
#include <tqdom.h>
#include <tqregexp.h>

XMLNewsArticle::XMLNewsArticle(const TQString &headline, const KURL &address)
	: m_headline(headline),
	m_address(address)
{
}

XMLNewsArticle &XMLNewsArticle::operator=(const XMLNewsArticle &other)
{
	m_headline = other.m_headline;
	m_address = other.m_address;
	return *this;
}

bool XMLNewsArticle::operator==(const XMLNewsArticle &a)
{
	return m_headline == a.headline() && m_address == a.address();
}

XMLNewsSource::XMLNewsSource() : TQObject(),
 	m_name(TQString()),
	m_link(TQString()),
	m_description(TQString()),
	m_downloadData(0)
{
}

XMLNewsSource::~XMLNewsSource()
{
	delete m_downloadData; // Might exist if we are in the middle of a download
}

void XMLNewsSource::loadFrom(const KURL &url)
{
	if ( m_downloadData != 0 ) {
		kdDebug( 5005 ) << "XMLNewsSource::loadFrom(): Busy, ignoring load "
		                   "request for " << url << endl;
		return;
	}
	m_downloadData = new TQBuffer;
	m_downloadData->open(IO_WriteOnly);

	TDEIO::Job *job = TDEIO::get(url, false, false);
	job->addMetaData(TQString::fromLatin1("UserAgent"),
	                 TQString::fromLatin1("KNewsTicker v0.2"));
	connect(job, TQT_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
			TQT_SLOT(slotData(TDEIO::Job *, const TQByteArray &)));
	connect(job, TQT_SIGNAL(result(TDEIO::Job *)), TQT_SLOT(slotResult(TDEIO::Job *)));
}

void XMLNewsSource::slotData(TDEIO::Job *, const TQByteArray &data)
{
	m_downloadData->writeBlock(data.data(), data.size());
}

void XMLNewsSource::slotResult(TDEIO::Job *job)
{
	kdDebug(5005) << "XMLNewsSource::slotResult(): Finished downloading data (" << job->error() << ")." << endl;
	processData(m_downloadData->buffer(), !job->error());
	delete m_downloadData;
	m_downloadData = 0;
}

void XMLNewsSource::processData(const TQByteArray &data, bool okSoFar)
{
	bool validContent = okSoFar;
	kdDebug(5005) << "XMLNewsSource::processData(): validContent = " << validContent << endl;
	
	if (okSoFar) {
		/*
		 * Some servers prepend whitespace before the <?xml...?> declaration.
		 * Since TQDom doesn't like that we strip this first.
		 */
		TQDomDocument domDoc;

		const char *charData = data.data();
		int len = data.count();

		while (len && (*charData == ' ' || *charData == '\n' || *charData == '\t' || *charData == '\r') ) {
			len--;
			charData++;
		}

		TQByteArray tmpData;
		tmpData.setRawData(charData, len);

		if (validContent = domDoc.setContent(tmpData)) {
			TQDomNode channelNode = domDoc.documentElement().namedItem(TQString::fromLatin1("channel"));
	
			m_name = channelNode.namedItem(TQString::fromLatin1("title")).toElement().text().simplifyWhiteSpace();
			kdDebug(5005) << "XMLNewsSource::processData(): Successfully updated " << m_name << endl;
			m_link = channelNode.namedItem(TQString::fromLatin1("link")).toElement().text().simplifyWhiteSpace();
			m_description = channelNode.namedItem(TQString::fromLatin1("description")).toElement().text().simplifyWhiteSpace();

			TQDomNodeList items = domDoc.elementsByTagName(TQString::fromLatin1("item"));
			m_articles.clear();
			TQDomNode itemNode;
			TQString headline, address;
			for (unsigned int i = 0; i < items.count(); i++) {
				itemNode = items.item(i);
				headline = KCharsets::resolveEntities(itemNode.namedItem(TQString::fromLatin1("title")).toElement().text().simplifyWhiteSpace());
				address = KCharsets::resolveEntities(itemNode.namedItem(TQString::fromLatin1("link")).toElement().text().simplifyWhiteSpace());
				m_articles.append(XMLNewsArticle(headline, KURL( address )));
			}
		}
		kdDebug(5005) << "XMLNewsSource::processData(): validContent = " << validContent << endl;
		tmpData.resetRawData(charData, len);
	}

	emit loadComplete(this, validContent);
}

#include "xmlnewsaccess.moc"