/***************************************************************************
                          kbeardirsize.cpp  -  description
                             -------------------
    begin                : tis sep 17 2002
    copyright            : (C) 2003 by Björn Sahlström
    email                : kbjorn@users.sourceforge.net
 ***************************************************************************/

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

//////////////////////////////////////////////////////////////////////
// Qt specific include files
#include <qapplication.h>
#include <qtimer.h>
//////////////////////////////////////////////////////////////////////
// KDE specific include files
#include <kdebug.h>
//////////////////////////////////////////////////////////////////////
// Application specific include files
#include "kbeardirsize.h"
#include "connectionmanager.h"
#include "kbearlistjob.h"

using namespace KBear;

#include "kbeardirsize.moc"

using namespace KIO;

KBearDirSize::KBearDirSize( int id, const KURL & directory )
    : KIO::Job(false /*No GUI*/), m_bAsync(true), m_totalSize(0L), m_ID( id )
{
    startNextJob( directory );
}

KBearDirSize::KBearDirSize( int id, const KFileItemList & lstItems )
    : KIO::Job(false /*No GUI*/), m_bAsync(true), m_totalSize(0L), m_lstItems(lstItems), m_ID( id )
{
    QTimer::singleShot( 0, this, SLOT(processList()) );
}

void KBearDirSize::processList()
{
    while (!m_lstItems.isEmpty())
    {
        KFileItem * item = m_lstItems.first();
        m_lstItems.removeFirst();
	if ( !item->isLink() )
	{
            if ( item->isDir() )
            {
                kdDebug() << "KBearDirSize::processList dir -> listing" << endl;
                KURL url = item->url();
                startNextJob( url );
                return; // we'll come back later, when this one's finished
            }
            else
            {
                m_totalSize += item->size();
// no long long with kdDebug()
//            kdDebug() << "KBearDirSize::processList file -> " << m_totalSize << endl;
            }
	}
    }
    kdDebug() << "KBearDirSize::processList finished" << endl;
    if ( !m_bAsync )
        qApp->exit_loop();
    emitResult();
}

void KBearDirSize::startNextJob( const KURL & url )
{
    KBearListJob * listJob = KBearListJob::listRecursive( m_ID, url, false, true );
    ConnectionManager::getInstance()->attachJob( m_ID, listJob );
	connect( listJob, SIGNAL(entries( KIO::Job *, const KIO::UDSEntryList& )),
             SLOT( slotEntries( KIO::Job*, const KIO::UDSEntryList& )));
    connect( listJob, SIGNAL(infoMessage( KIO::Job *, const QString& )),
             this, SLOT( infoMessage( KIO::Job*, const QString& )));
    addSubjob( listJob );
}

void KBearDirSize::slotEntries( KIO::Job*, const KIO::UDSEntryList & list )
{
    KIO::UDSEntryListConstIterator it = list.begin();
    KIO::UDSEntryListConstIterator end = list.end();
    for (; it != end; ++it) {
        KIO::UDSEntry::ConstIterator it2 = (*it).begin();
        KIO::filesize_t size = 0;
        bool isLink = false;
        QString name;
        for( ; it2 != (*it).end(); it2++ ) {
          switch( (*it2).m_uds ) {
            case KIO::UDS_NAME:
              name = (*it2).m_str;
              break;
            case KIO::UDS_LINK_DEST:
              isLink = !(*it2).m_str.isEmpty();
              break;
            case KIO::UDS_SIZE:
              size = ((*it2).m_long);
              break;
            default:
              break;
          }
        }
        if ( !isLink && name != QString::fromLatin1("..") )
        {
            m_totalSize += size;
            //kdDebug() << name << ":" << size << endl;
        }
    }
}

//static
KBearDirSize * KBearDirSize::dirSizeJob( int id, const KURL & directory )
{
    return new KBearDirSize( id, directory ); // useless - but consistent with other jobs
}

//static
KBearDirSize * KBearDirSize::dirSizeJob( int id, const KFileItemList & lstItems )
{
    return new KBearDirSize( id, lstItems );
}

//static
/*
KIO::filesize_t KBearDirSize::dirSize( const KURL & directory )
{
    KBearDirSize * dirSize = dirSizeJob( m_ID, directory );
    dirSize->setSync();
    qApp->enter_loop();
    return dirSize->totalSize();
}
*/

void KBearDirSize::slotResult( KIO::Job * job )
{
    kdDebug() << " KBearDirSize::slotResult( KIO::Job * job ) m_lstItems:" << m_lstItems.count() << endl;
    if ( !m_lstItems.isEmpty() )
    {
        subjobs.remove(job); // Remove job, but don't kill this job.
        processList();
    }
    else
    {
        if ( !m_bAsync )
            qApp->exit_loop();
        KIO::Job::slotResult( job );
    }
}


