/*
    task.cpp - Kopete Groupwise Protocol

    Copyright (c) 2004      SUSE Linux AG	 	 http://www.suse.com

    Based on Iris, Copyright (C) 2003  Justin Karneges

    Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/
  
#include <tqtimer.h>

#include "connection.h"
#include "transfer.h"
#include "safedelete.h"
#include "buffer.h"
#include "task.h"


class Task::TaskPrivate
{
public:
	TaskPrivate() {}

	TQ_UINT32 id;
	bool success;
	int statusCode;
	TQString statusString;
	Connection* client;
	bool insignificant, deleteme, autoDelete;
	bool done;
	Transfer* transfer;
};

Task::Task(Task *parent)
:TQObject(parent)
{
	init();
	d->client = parent->client();
	connect(d->client, TQ_SIGNAL(disconnected()), TQ_SLOT(clientDisconnected()));
}

Task::Task(Connection* parent, bool)
:TQObject(0)
{
	init();
	d->client = parent;
	connect(d->client, TQ_SIGNAL(disconnected()), TQ_SLOT(clientDisconnected()));
}

Task::~Task()
{
	delete d->transfer;
	delete d;
}

void Task::init()
{
	d = new TaskPrivate;
	d->success = false;
	d->insignificant = false;
	d->deleteme = false;
	d->autoDelete = false;
	d->done = false;
	d->transfer = 0;
	d->id = 0;
}

Task *Task::parent() const
{
	return (Task *)TQObject::parent();
}

Connection *Task::client() const
{
	return d->client;
}

Transfer * Task::transfer() const
{
	return d->transfer;
}

void Task::setTransfer( Transfer * transfer )
{
	d->transfer = transfer;
}

long Task::id() const
{
	return d->id;
}

bool Task::success() const
{
	return d->success;
}

int Task::statusCode() const
{
	return d->statusCode;
}

const TQString & Task::statusString() const
{
	return d->statusString;
}

void Task::go(bool autoDelete)
{
	d->autoDelete = autoDelete;

	onGo();
}

bool Task::take( Transfer * transfer)
{
	const TQObjectList p = childrenListObject();
	if(p.isEmpty())
		return false;

	// pass along the transfer to our children
	TQObjectListIt it(p);
	Task *t;
	for(; it.current(); ++it) {
		TQObject *obj = it.current();
		if(!obj->inherits("Task"))
			continue;

		t = static_cast<Task*>(obj);
		
		if(t->take( transfer ))
		{
			//tqDebug( "Transfer ACCEPTED by: %s", t->className() );
			return true;
		}
		//else
			//tqDebug( "Transfer refused by: %s", t->className() );
	}

	return false;
}

void Task::safeDelete()
{
	if(d->deleteme)
		return;

	d->deleteme = true;
	if(!d->insignificant)
		SafeDelete::deleteSingle(this);
}

void Task::onGo()
{
	tqDebug( "ERROR: calling default NULL onGo() for this task, you should reimplement this!");
}

void Task::onDisconnect()
{
	if(!d->done) {
		d->success = false;
		d->statusCode = ErrDisc;
		d->statusString = tr("Disconnected");

		// delay this so that tasks that react don't block the shutdown
		TQTimer::singleShot(0, this, TQ_SLOT(done()));
	}
}

void Task::send( Transfer * request )
{
	client()->send( request );
}

void Task::setSuccess(int code, const TQString &str)
{
	if(!d->done) {
		d->success = true;
		d->statusCode = code;
		d->statusString = str;
		done();
	}
}

void Task::setError(int code, const TQString &str)
{
	if(!d->done) {
		d->success = false;
		d->statusCode = code;
		d->statusString = str;
		done();
	}
}

void Task::done()
{
	debug("Task::done()");
	if(d->done || d->insignificant)
		return;
	d->done = true;

	if(d->deleteme || d->autoDelete)
		d->deleteme = true;

	d->insignificant = true;
	debug("emitting finished");
	finished();
	d->insignificant = false;

	if(d->deleteme)
		SafeDelete::deleteSingle(this);
}

void Task::clientDisconnected()
{
	onDisconnect();
}

Transfer* Task::createTransfer( struct FLAP f, struct SNAC s, Buffer* buffer )
{
	return new SnacTransfer( f, s, buffer );
}

Transfer* Task::createTransfer( struct FLAP f, Buffer* buffer )
{
	return new FlapTransfer( f, buffer );
}

Transfer* Task::createTransfer( Buffer* buffer )
{
	return new Transfer( buffer );
}


// void Task::debug(const char *fmt, ...)
// {
// 	char *buf;
// 	TQString str;
// 	int size = 1024;
// 	int r;
// 
// 	do {
// 		buf = new char[size];
// 		va_list ap;
// 		va_start(ap, fmt);
// 		r = vsnprintf(buf, size, fmt, ap);
// 		va_end(ap);
// 
// 		if(r != -1)
// 			str = TQString(buf);
// 
// 		delete [] buf;
// 
// 		size *= 2;
// 	} while(r == -1);
// 
// 	debug(str);
// }

void Task::debug(const TQString &str)
{
	//black hole
	Q_UNUSED( str );
	//client()->debug(TQString("%1: ").arg(className()) + str);
}

bool Task::forMe( const Transfer * transfer ) const
{
	Q_UNUSED( transfer );
	return false;
}

void Task::setId( TQ_UINT32 id )
{
	d->id = id;
}

#include "task.moc"
