// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// version 2 as published by the Free Software Foundation.
//
// 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; see the file COPYING.  If not, write to
// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
// Boston, MA 02110-1301, USA.

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

#include <kextendedsocket.h>

#include "monopigator.moc"
#include "main.h"

Monopigator::Monopigator()
{
	m_downloadData = 0;
	m_job = 0;
	m_timer = 0;
}

Monopigator::~Monopigator()
{
	if (m_job)
		m_job -> kill();
        delete m_downloadData;
        m_downloadData=0L;
}

void Monopigator::loadData(const KURL &url)
{
    delete m_downloadData;
	m_downloadData = new TQBuffer();
	m_downloadData->open(IO_WriteOnly);
	m_downloadData->reset();

	m_job = TDEIO::get(url, true, false);
	m_job->addMetaData(TQString::fromLatin1("UserAgent"), TQString::fromLatin1("Atlantik/" ATLANTIK_VERSION_STRING));

	if (!m_timer)
	{
		m_timer = new TQTimer(this);
		m_timer->start(10000, true);
	}

	connect(m_job, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)), TQ_SLOT(slotData(TDEIO::Job *, const TQByteArray &)));
	connect(m_job, TQ_SIGNAL(result(TDEIO::Job *)), TQ_SLOT(slotResult(TDEIO::Job *)));
	connect(m_timer, TQ_SIGNAL(timeout()), TQ_SLOT(slotTimeout()));
}

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

void Monopigator::slotResult(TDEIO::Job *job)
{
	processData(m_downloadData->buffer(), !job->error());
	m_job = 0;
}

void Monopigator::slotTimeout()
{
	if (m_job)
		m_job -> kill();
	m_job = 0;

	emit timeout();
}

void Monopigator::processData(const TQByteArray &data, bool okSoFar)
{
	if (okSoFar)
	{
		TQString xmlData(data);
		TQDomDocument domDoc;
		if (domDoc.setContent(xmlData))
		{
			TQDomElement eTop = domDoc.documentElement();
			if (eTop.tagName() != "monopigator")
				return;

			TQDomNode n = eTop.firstChild();
			while(!n.isNull())
			{
				TQDomElement e = n.toElement();
				if(!e.isNull())
				{
					if (e.tagName() == "server")
						emit monopigatorAdd(e.attributeNode(TQString("ip")).value(), e.attributeNode(TQString("host")).value(), e.attributeNode(TQString("port")).value(), e.attributeNode(TQString("version")).value(), e.attributeNode(TQString("users")).value().toInt());
				}
				n = n.nextSibling();
			}
			emit finished();
		}
	}
}

MonopigatorEntry::MonopigatorEntry(TQListView *parent, TQString host, TQString latency, TQString version, TQString users, TQString port, TQString ip) : TQObject(), TQListViewItem(parent, host, latency, version, users, port)
{
	m_isDev = ( version.find( TQRegExp("(CVS|-dev)") ) != -1 ) ? true : false;

	setEnabled(false);
	parent->sort();

	if ( !ip.isEmpty() )
		host = ip;
	m_latencySocket = new KExtendedSocket( host, port.toInt(), KExtendedSocket::inputBufferedSocket | KExtendedSocket::noResolve );
	connect(m_latencySocket, TQ_SIGNAL(lookupFinished(int)), this, TQ_SLOT(resolved()));
	connect(m_latencySocket, TQ_SIGNAL(connectionSuccess()), this, TQ_SLOT(connected()));
	m_latencySocket->startAsyncConnect();
}

void MonopigatorEntry::resolved()
{
	time.start();
}

void MonopigatorEntry::connected()
{
	setText( 1, TQString::number(time.elapsed()) );
	setEnabled(true);
	listView()->sort();
	delete m_latencySocket;
}

int MonopigatorEntry::compare(TQListViewItem *i, int col, bool ascending) const
{
	// Colums 1 and 3 are integers (latency and users)
	if (col == 1 || col == 3)
	{
		int myVal = text(col).toInt(), iVal = i->text(col).toInt();
		if (myVal == iVal)
			return 0;
		else if (myVal > iVal)
			return 1;
		else
			return -1;
	}
	return key( col, ascending ).compare( i->key( col, ascending) );
}

bool MonopigatorEntry::isDev() const
{
	return m_isDev;
}

void MonopigatorEntry::showDevelopmentServers(bool show)
{
	if ( isVisible() != show )
		setVisible(show);
}
