/*********************************************************************************
* C++ Implementation: transfer.cpp
* Description:
*
* Begin : ons maj 7 2003
* Author : Björn Sahlström <kbjorn@users.sourceforge.net> (C) 2003
* Copyright : See COPYING file that comes with this distribution
**********************************************************************************/

//////////////////////////////////////////////////////////////////////
// Qt specific include files
#include <qvaluestack.h>
#include <qapplication.h>
#include <qstringlist.h>
//////////////////////////////////////////////////////////////////////
// KDE specific include files
#include <kdebug.h>
#include <kmessagebox.h>
#include <kparts/dockmainwindow.h>
//////////////////////////////////////////////////////////////////////
// System specific include files
//////////////////////////////////////////////////////////////////////
// Application specific include files
#include "transfer.h"
#include "transfergroup.h"
#include "transfermanager.h"
#include "connectionmanager.h"
#include "kbearcopyjob.h"
#include "kbearmainwiniface.h"

#include "transfer.moc"


using namespace KBear;
//-----------------------------------------------
class Transfer::TransferPrivate {
	public:
};
//-----------------------------------------------
Transfer::Transfer( TransferGroup* group, int ID, const SiteInfo& sInfo, const SiteInfo& dInfo, unsigned int type, const QString& mimetype )
	:	d( new TransferPrivate ),
		m_sourceID( -1 ), m_destID( -1 ),
		m_transferID( -1 ), m_status( Uninitialized ),
		m_type( Copy ), m_autoSkip( false ), m_overwriteAll( false ),
		m_size( 0 ), m_progress( 0 ), m_sourceInfo( sInfo ), m_destInfo( dInfo )
{
	m_sourceInfo = sInfo;
	m_destInfo = dInfo;
	if( ! m_sourceInfo.isLocal() ) {
		ConnectionManager::getInstance()->createNewConnection( m_sourceInfo );
	}
	if( ! m_destInfo.isLocal() ) {
		ConnectionManager::getInstance()->createNewConnection( m_destInfo );
	}
	m_transferID = ID;
	m_type = type;
	m_mimetype = mimetype;
	m_group = group;
}
//-----------------------------------------------
Transfer::Transfer( TransferGroup* group, int ID, int sourceID, int destID, unsigned int type, const QString& mimetype )
	:	d( new TransferPrivate ),
		m_transferID( -1 ), m_status( Uninitialized ),
		m_type( Copy ), m_autoSkip( false ), m_overwriteAll( false ),
		m_size( 0 ), m_progress( 0 )
{
	m_sourceID = sourceID;
	m_destID = destID;
	if( m_sourceID >= 0 )
		m_sourceInfo = ConnectionManager::getInstance()->getSiteInfo( m_sourceID );
	if( m_destID >= 0 )
		m_destInfo = ConnectionManager::getInstance()->getSiteInfo( m_destID );
	if( ! m_sourceInfo.isLocal() ) {
		ConnectionManager::getInstance()->createNewConnection( m_sourceInfo );
	}
	if( ! m_destInfo.isLocal() ) {
		ConnectionManager::getInstance()->createNewConnection( m_destInfo );
	}

	m_transferID = ID;
	m_type = type;
	m_mimetype = mimetype;
	m_group = group;
}
//-----------------------------------------------
Transfer::~Transfer() {
	ConnectionManager::getInstance()->closeConnection( m_sourceInfo.ID() );
	ConnectionManager::getInstance()->closeConnection( m_destInfo.ID() );
	delete d;
}
//-----------------------------------------------
void Transfer::setCommand( unsigned int cmd ) {
	kdDebug()<<k_funcinfo<<" Command="<<cmd<<endl;
	switch ( cmd ) {
		case Start: {
			if( status() == Started ) {
				kdError()<<k_funcinfo<<" Start called on already started transfer!!!!!!!"<<endl;
				break;
			}
			if( m_type == Copy )
				m_job = new KBearCopyJob( this, KBearCopyJob::Copy, false );
			else
				m_job = new KBearCopyJob( this, KBearCopyJob::Move, false );
			m_job->setSkipAll( m_autoSkip );
			m_job->setOverwriteAll( m_overwriteAll );
			connectJob();
			KBearCopyJob* job = m_job;
			job->slotStart( m_sourceInfo.ID(), m_destInfo.ID() );
			setStatus( Started );
			break;
		}
		case Queue: {
			if( status() == Paused ) {
				ConnectionManager::getInstance()->resume( m_sourceInfo.ID() );
				ConnectionManager::getInstance()->resume( m_destInfo.ID() );
			}
			if( m_job )
				m_job->kill(true);

			setStatus( Queued );
			break;
		}
		case Pause: {
			ConnectionManager::getInstance()->suspend( m_sourceInfo.ID() );
			ConnectionManager::getInstance()->suspend( m_destInfo.ID() );
			setStatus( Paused );
			break;
		}
		case Resume: {
			ConnectionManager::getInstance()->resume( m_sourceInfo.ID() );
			ConnectionManager::getInstance()->resume( m_destInfo.ID() );
			setStatus( Started );
			break;
		}
		case Stop: {
			if( m_job ) {
				m_job->kill(true);
			}
			setStatus( Stopped );
			break;
		}
		case Cancel: {
			if( m_job ) {
				m_job->kill(true);
			}
			setStatus( Canceled );
		}
		default: { // e.g Die
			if( m_job ) {
				m_job->kill(true);
			}
			break;
		}
	}
}
//-----------------------------------------------
void Transfer::connectJob() {
	if( ! m_job )
		return;
	m_job->setAutoErrorHandlingEnabled( true, qApp->mainWidget() );
	connect( m_job, SIGNAL( result( KIO::Job* ) ),
						this, SLOT( slotResult( KIO::Job* ) ) );
	connect( m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
						this, SLOT( slotPercent( KIO::Job*, unsigned long ) ) );
	connect( m_job, SIGNAL( totalDirs( KIO::Job*, unsigned long ) ),
						this, SLOT( slotTotalDirs( KIO::Job *, unsigned long ) ) );
	connect( m_job, SIGNAL( totalFiles( KIO::Job *, unsigned long ) ),
						this, SLOT( slotTotalFiles( KIO::Job *, unsigned long ) ) );
	connect( m_job, SIGNAL( processedFiles( KIO::Job *, unsigned long ) ),
						this, SLOT( slotProcessedFiles( KIO::Job *, unsigned long ) ) );
	connect( m_job, SIGNAL( processedDirs( KIO::Job *, unsigned long ) ),
						this, SLOT( slotProcessedDirs( KIO::Job *, unsigned long ) ) );
	connect( m_job, SIGNAL( copying( KIO::Job *, const KURL&, const KURL& ) ),
						this, SLOT( slotCopying( KIO::Job *, const KURL&, const KURL& ) ) );
	connect( m_job, SIGNAL( moving( KIO::Job *, const KURL&, const KURL& ) ),
						this, SLOT( slotMoving( KIO::Job *, const KURL&, const KURL& ) ) );
	connect( m_job, SIGNAL( creatingDir( KIO::Job *, const KURL& ) ),
						this, SLOT( slotCreatingDir( KIO::Job *, const KURL& ) ) );
	connect( m_job, SIGNAL( renamed( KIO::Job *, const KURL&, const KURL& ) ),
						this, SLOT( slotRenamed( KIO::Job *, const KURL&, const KURL& ) ) );
	connect( m_job, SIGNAL( canceled( KIO::Job* ) ),
						this, SLOT( slotCanceled( KIO::Job* ) ) );
	connect( m_job, SIGNAL( totalSize( KIO::Job *, KIO::filesize_t ) ),
						this, SLOT( slotTotalSize( KIO::Job *, KIO::filesize_t ) ) );
	connect( m_job, SIGNAL( processedSize( KIO::Job *, KIO::filesize_t ) ),
						this, SLOT( slotProcessedSize( KIO::Job *, KIO::filesize_t ) ) );
	connect( m_job, SIGNAL( speed( KIO::Job *, unsigned long ) ),
						this, SLOT( slotSpeed( KIO::Job *, unsigned long ) ) );
}
//-----------------------------------------------
void Transfer::setStatus( unsigned int s ) {
	// we need to look what status to set since not all are valid at all times
	// TODO
	switch( s ) {
		case Started:
			break;
		case Stopped:
			setCommand( Die );
			break;
		case Paused:
			break;
		case Queued:
			break;
		case Canceled:
			break;
		case Finished:
			emit finished();
			break;
		case Uninitialized:
			break;
		default:
			break;
	};

	m_status = s;
	emit statusChanged( m_transferID, m_status );
}
//-----------------------------------------------
void Transfer::setSourceURLs( const KURL::List& urls ) {
	m_sourceURLs = urls;
}
//-----------------------------------------------
void Transfer::setDestURL( const KURL& url ) {
	m_destURL = url;
}
//-----------------------------------------------
void Transfer::slotPercent( KIO::Job*, unsigned long p ) {
	m_progress = p;
	emit percent( m_transferID, p );
}
//-----------------------------------------------
void Transfer::slotTotalDirs( KIO::Job *, unsigned long dirs ) {
	emit totalDirs( m_transferID, dirs );
}
//-----------------------------------------------
void Transfer::slotTotalFiles( KIO::Job *, unsigned long files ) {
	emit totalFiles( m_transferID, files );
}
//-----------------------------------------------
void Transfer::slotProcessedFiles( KIO::Job *, unsigned long files ) {
	emit processedFiles( m_transferID, files );
}
//-----------------------------------------------
void Transfer::slotProcessedDirs( KIO::Job *, unsigned long dirs ) {
	emit processedDirs( m_transferID, dirs );
}
//-----------------------------------------------
void Transfer::slotCopying( KIO::Job *, const KURL& from, const KURL& to ) {
	emit copying( m_transferID, from, to );
}
//-----------------------------------------------
void Transfer::slotMoving( KIO::Job *, const KURL& from, const KURL& to ) {
	emit moving( m_transferID, from, to );
}
//-----------------------------------------------
void Transfer::slotCreatingDir( KIO::Job *, const KURL& dir ) {
	emit creatingDir( m_transferID, dir );
}
//-----------------------------------------------
void Transfer::slotRenamed( KIO::Job *, const KURL& from, const KURL& to ) {
	emit renamed( m_transferID, from, to );
}
//-----------------------------------------------
void Transfer::slotCanceled( KIO::Job* ) {
	setStatus( Canceled );
}
//-----------------------------------------------
void Transfer::slotTotalSize( KIO::Job *, KIO::filesize_t size ) {
	m_size = size;
	emit totalSize( m_transferID, size );
}
//-----------------------------------------------
void Transfer::slotProcessedSize( KIO::Job *, KIO::filesize_t size ) {
	emit processedSize( m_transferID, size );
}
//-----------------------------------------------
void Transfer::slotSpeed( KIO::Job *, unsigned long bytes_per_second ){
	emit speed( m_transferID, bytes_per_second );
}
//-----------------------------------------------
void Transfer::setOverWrite( bool overwrite ) {
	m_overwriteAll = overwrite;
	if( m_job )
		m_job->setOverwriteAll( overwrite );
}
//-----------------------------------------------
void Transfer::setSkip( bool skip ) {
	m_autoSkip = skip;
	if( m_job )
		m_job->setSkipAll( skip );
}
//-----------------------------------------------
void Transfer::slotResult( KIO::Job* job ){
	int error = job->error();
	if( error ) {
/*
		QApplication::restoreOverrideCursor();
		QStringList list = job->detailedErrorStrings();
		KMessageBox::detailedError( qApp->mainWindget(, list[1], list[2], list[0] );
*/
		setStatus( Canceled );
	}
	else {
		slotPercent( job, 100 );
		setStatus( Finished );
	}

}
//-----------------------------------------------

