#include <noatun/downloader.h>
#include <noatun/app.h>
#include <assert.h>
#include <tqfile.h>
#include <tqtimer.h>
#include <tdeio/job.h>
#include <tdelocale.h>

DownloadItem::DownloadItem()
{

}

DownloadItem::~DownloadItem()
{
	dequeue();
}

bool DownloadItem::isDownloaded() const
{
	return true;
}

TQString DownloadItem::localFilename() const
{
	return mLocalFilename;
}

void DownloadItem::setLocalFilename(const TQString &filename)
{
	mLocalFilename=filename;
}

void DownloadItem::downloadFinished()
{
}

void DownloadItem::downloaded(int )
{
}

void DownloadItem::downloadTimeout()
{
}

bool DownloadItem::enqueue(const KURL &url)
{
	if (url.isLocalFile())
	{
		setLocalFilename(url.path());
		return false;
	}
	else
	{
		napp->downloader()->enqueue(this, url);
		return true;
	}
}

void DownloadItem::dequeue()
{
	napp->downloader()->dequeue(this);
}




Downloader::Downloader(TQObject *parent)
	: TQObject(parent), localfile(0), current(0), mJob(0), mTimeout(0)
{
	mStarted=false;
	mUnstartedQueue=new TQPtrList<Downloader::QueueItem>;
}

Downloader::~Downloader()
{

}

void Downloader::start()
{
	assert(!mStarted);
	mStarted=true;
	if (current)
		emit enqueued(current->notifier, current->file);

	for (TQPtrListIterator<Downloader::QueueItem> i(*mUnstartedQueue); i.current(); ++i)
	{
		(*i)->notifier->mLocalFilename = (*i)->local;
		mQueue.append(*i);
		emit enqueued((*i)->notifier, (*i)->file);
	}
	
	delete mUnstartedQueue;
	mUnstartedQueue=0;
	TQTimer::singleShot(0, this, TQT_SLOT(getNext()));
}

static TQString nonExistantFile(const TQString &file)
{
	if (file.right(1)=="/") return i18n("Unknown");
	int i=0;
	TQString f(file);
	while (TQFile(f).exists())
	{
		i++;
		f=file;
		f.insert(f.findRev('.'), '_'+TQString::number(i));
	}
	return f;
}

TQString Downloader::enqueue(DownloadItem *notifier, const KURL &file)
{
	if (file.isLocalFile()) return 0;
	QueueItem *i=new QueueItem;
	i->notifier=notifier;
	i->file=file;
	
	if (!mStarted)
	{
		i->local=notifier->mLocalFilename;
		if (!notifier->localFilename().length())
		{
			i->local = 
				nonExistantFile(napp->saveDirectory()+'/'+file.fileName());
		}
		mUnstartedQueue->append(i);
		return i->local;
	}
	
	
	if (!notifier->localFilename().length())
	{
		notifier->mLocalFilename=
			i->local =
				nonExistantFile(napp->saveDirectory()+'/'+file.fileName());
	}
	else
	{
		i->local = notifier->mLocalFilename;
	}

	mQueue.append(i);
	TQTimer::singleShot(0, this, TQT_SLOT(getNext()));
	emit enqueued(notifier, file);
	return i->local;
}

void Downloader::dequeue(DownloadItem *notifier)
{
	if (current && notifier==current->notifier)
	{
		mJob->kill();
		jobDone(mJob);
		return;
	}
	for (TQPtrListIterator<Downloader::QueueItem> i(mQueue); i.current(); ++i)
	{
		if ((*i)->notifier==notifier)
		{
			mQueue.removeRef(*i);
			if (mStarted)
				emit dequeued(notifier);
			delete *i;
			return;
		}
	}
}

void Downloader::getNext()
{
	if (current) return;
	if (!mStarted) return;
	if (mQueue.isEmpty()) return;
	current=mQueue.take(0);

	// open the TQFile
	localfile=new TQFile(current->local);
	localfile->open(IO_ReadWrite | IO_Append);

	mJob= TDEIO::get(current->file, true, false);
	connect(mJob, TQT_SIGNAL(data(TDEIO::Job*, const TQByteArray&)), TQT_SLOT(data(TDEIO::Job*, const TQByteArray&)));
	connect(mJob, TQT_SIGNAL(result(TDEIO::Job*)), TQT_SLOT(jobDone(TDEIO::Job*)));
	connect(mJob, TQT_SIGNAL(percent(TDEIO::Job*, unsigned long)), TQT_SLOT(percent(TDEIO::Job*, unsigned long)));

	if (mTimeout)
		delete mTimeout;
	mTimeout=new TQTimer(this);
	mTimeout->start(30000, true);
	connect(mTimeout, TQT_SIGNAL(timeout()), TQT_SLOT(giveUpWithThisDownloadServerIsRunningNT()));
}

void Downloader::data(TDEIO::Job *, const TQByteArray &data)
{
	localfile->writeBlock(data);
	localfile->flush();
	delete mTimeout;
	mTimeout=0;
}

void Downloader::jobDone(TDEIO::Job *)
{
	delete mTimeout;
	mTimeout=0;
	current->notifier->downloadFinished();
	if (mStarted)
		emit dequeued(current->notifier);
	delete current;
	current=0;
	mJob=0;
	getNext();
}

void Downloader::giveUpWithThisDownloadServerIsRunningNT()
{
	delete mTimeout;
	mTimeout=0;
	if (!current) return;
	DownloadItem *old=current->notifier;
	if (!old) return;	
	old->downloadTimeout();
	current=0;
	mJob=0;
	delete old;
	getNext();
}

void Downloader::percent( TDEIO::Job *, unsigned long percent)
{
	if (current && current->notifier)
		current->notifier->downloaded((int)percent);
}

#include "downloader.moc"

