/***************************************************************************
 *   Copyright (C) 2004, 2005 by Johnathan Burchill                        *
 *   jkerrb@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.                                   *
 ***************************************************************************/

#include "kdarcontroller.h"
#include "kdarListViewItem.h"

#include "kdardeclarations.h"
#include "kdarview.h"
#include "archiveHandle.h"

#include "createArchiveThread.h"
#include "diffArchiveThread.h"
#include "isolateArchiveThread.h"
#include "listArchiveThread.h"
#include "openArchiveThread.h"
#include "populateTreeArchiveThread.h"
#include "restoreArchiveThread.h"
#include "testArchiveThread.h"

#include "kdarArchiveBrowserUpdatesEvent.h"
#include "kdarCancelButtonEvent.h"
#include "kdarCheckFileSizeEvent.h"
#include "kdardeletethreadevent.h"
#include "kdarLogFileCommandEvent.h"
#include "kdarPostListViewItemEvent.h"
#include "kdarProgressEvent.h"
#include "kdarProgressDialogEvent.h"
#include "kdarSetCursorEvent.h"
#include "kdarStatusBarEvent.h"
#include "kdarTarListingEvent.h"
#include "kdarUserInteractionEvent.h"
#include "kdarUserInteractionStringEvent.h"
#include "kdarWarningEvent.h"

#include "kdarConfig.h"

#include <kcursor.h>
#include <kdebug.h>
#include <kfiledialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpassdlg.h>

#include <qapplication.h>
#include <qevent.h>
#include <qsemaphore.h>
#include <qwidget.h>

#include <dar/libdar.hpp>

extern bool libdarWorking;
extern kdarListViewItem* currentDirectory;
extern libdar::archive *theArchive;

KDarController::KDarController()
{
    //Initialize pointers to zero:
    m_createThread = 0;
    m_diffThread = 0;
    m_isolateThread = 0;
    m_listThread = 0;
    m_openThread = 0;
    m_populateTreeThread = 0;
    m_restoreThread = 0;
    m_testThread = 0;
    m_localWallet = 0;
    m_password = "";
    m_userResponse = false;
    kdDebug() << "KDarController::KDarController(): QSemaphore craziness" << endl;
    m_semaphore = new QSemaphore( 1 );
    ( *m_semaphore )++;

    //Set up the libdar capabilities info
    libdar::get_compile_time_features( m_handlesEA, m_handlesLargefiles, m_handlesNoDump, m_usesSpecialAlloc, m_integerSizeBits, m_isThreadSafe, m_handlesZCompression, m_handlesBZ2Compression, m_handlesStrongCrypto );

}

KDarController::~KDarController()
{
    //Delete the KWallet
    if ( m_localWallet )
    {
        delete m_localWallet;
        m_localWallet = 0;
    }
    //Delete any running threads? Perhaps we need to make sure user
    //really intended to quit?
    if ( m_populateTreeThread )
    {
        m_populateTreeThread->wait();
        delete m_populateTreeThread;
        m_populateTreeThread = 0;
    }
    if ( m_listThread )
    {
        m_listThread->wait();
        delete m_listThread;
        m_listThread = 0;
    }
    if ( m_testThread )
    {
        m_testThread->wait();
        delete m_testThread;
        m_testThread = 0;
    }
    if ( m_restoreThread )
    {
        m_restoreThread->wait();
        delete m_restoreThread;
        m_restoreThread = 0;
    }
    if ( m_isolateThread )
    {
        m_isolateThread->wait();
        delete m_isolateThread;
        m_isolateThread = 0;
    }
    if ( m_diffThread )
    {
        m_diffThread->wait();
        delete m_diffThread;
        m_diffThread = 0;
    }
    if ( m_createThread )
    {
        m_createThread->wait();
        delete m_createThread;
        m_createThread = 0;
    }
}

bool KDarController::openKDEWallet()
{
    bool success = true;
    //Ask KDE for a wallet. If unsuccessful, we need to ask user
    //for password each time it is needed by libdar's encryption API
    m_localWallet = KWallet::Wallet::openWallet( KWallet::Wallet::LocalWallet() );
    //If the wallet couldn't be opened, we should be 0 for *localWallet.
    //Then we just test for ( localWallet ) when asked for a password, and
    //return "" if the wallet object does not exist.

    //Some things to keep in mind:
    if ( m_localWallet )
    {
        if ( !m_localWallet->hasFolder( KDARKWALLETFOLDER ) )
        {
            //Create the standard password folder
            kdDebug() << "KDarController::openKDEWallet(): m_localWallet has no KDARKWALLETFOLDER...creating it." << endl;
            int res = m_localWallet->createFolder( KDARKWALLETFOLDER );
            if ( !res )
            {
                kdDebug() << "KDarController::openKDEWallet(): could not create m_localWallet folder \"KDARKWALLETFOLDER\"." << endl;
                // close the wallet...?
                delete m_localWallet;
                m_localWallet = 0;
                success = false;
            }
        }
    }
    else
    {
        success = false;
    }
    return success;
}

void KDarController::closeArchive()
{
    if ( theArchive )
    {
        delete theArchive;
        theArchive = 0;
        kdDebug() << "Archive closed." << endl;
    }
}

void KDarController::closeLogFile()
{
    //close the log file
    m_logFile.close();
    m_logStream.unsetDevice();
    kdDebug() << "KDarController::closeLogFile()" << endl;
}

void KDarController::createArchive( KDarConfig * kdarconfig, bool updateListView )
{
    if (libdarWorking)
    {
        return;
    }
    //parse the new archive name for string substitutions:
    kdarconfig->setNewArchiveName( archiveHandle::parseStringSubstitutions( kdarconfig->newArchiveName(), kdarconfig ) );

    kdDebug() << "KDarController::createArchive(): newArchiveName is " << kdarconfig->newArchiveName() << endl;
    if ( kdarconfig->differentialBackup() )
    {
        kdDebug() << "KDarController::createArchive(): opening reference archive" << endl;
        openArchive( kdarconfig, updateListView );
    }
    kdDebug() << "starting create thread." << endl;
    m_createThread = new createArchiveThread( this, kdarconfig );
    std::cout << "priority is " << kdarconfig->priority() << std::endl;
    m_createThread->start( ( QThread::Priority ) kdarconfig->priority() );
    kdDebug() << "started create thread." << endl;
}

void KDarController::diffArchive( KDarConfig * kdarconfig )
{
    if (libdarWorking)
    {
        return;
    }
    if (theArchive == 0) return;
    QString diffArchiveDirectory = KFileDialog::getExistingDirectory( KDARDIRKEY, 0, (QString) "Select directory to diff");
    //if user cancels, do nothing
    if ( diffArchiveDirectory.isEmpty() ) return;
    kdDebug() << "KDarContoller::diffArchive() called: directory to diff is " << kdarconfig->diffArchiveDirectory() << endl;
    kdarconfig->setDiffArchiveDirectory( diffArchiveDirectory );
    kdDebug() << "KDarController::diffArchive(): creating and starting m_diffThread" << endl;
    m_diffThread = new diffArchiveThread( this, kdarconfig, m_parent->archiveFileView );
    m_diffThread->start();

}

void KDarController::isolateArchive( KDarConfig * kdarconfig )
{
    if (libdarWorking)
    {
        return;
    }
    if (theArchive == 0) return;

    //user picks isolated archive name
    QString isoArchiveName=KFileDialog::getSaveFileName( KDARDIRKEY, QString::null, 0, (QString) "Select a filename for new isolation archive");
    //if user cancels, do nothing
    if ( isoArchiveName.isEmpty() ) return;
    kdarconfig->setIsolationArchiveName( isoArchiveName );
    kdDebug() << "KDarContoller::isolateArchive() called: isolatation name is " << kdarconfig->isolationArchiveName() << endl;
    kdDebug() << "KDarController::isolateArchive(): creating and starting m_isolateThread" << endl;
    m_isolateThread = new isolateArchiveThread( this, kdarconfig );
    m_isolateThread->start();
}

void KDarController::listArchive( KDarConfig * kdarconfig, bool loadArchive )
{
    if (libdarWorking)
    {
        return;
    }
    if (theArchive == 0)
    {
        QString archiveName = kdarconfig->archiveName();
        if (archiveName[0] == '/' && loadArchive )
        {
            kdDebug() << "archive name to list is " << archiveName << endl;
            openArchive( kdarconfig );
        }
        else
        {
            return;
        }
    }
    m_listThread = new listArchiveThread( this, kdarconfig );
    m_listThread->start();
    kdDebug() << "KDarContoller::listArchive() called." << endl;
}

void KDarController::openArchive( KDarConfig * kdarconfig, bool updateListView )
{
    if (libdarWorking)
    {
        return;
    }
    //Close the archive object if one is open
    if ( theArchive ) closeArchive();

    QString archiveName = kdarconfig->archiveName();
    if (archiveName[0] != '/')
    {
        return;
    }
    kdDebug() << "KDarContoller::openArchive() starting m_openThread." << endl;
    m_openThread = new openArchiveThread( this, kdarconfig, updateListView );
    m_openThread->start();
}

void KDarController::openLogFile( const QString & logFile )
{
    //open the log file
    if ( m_logFile.isOpen() ) m_logFile.close();
    m_logFile.setName( logFile );
    m_logFile.open( IO_WriteOnly | IO_Append );
    m_logStream.setDevice( (QIODevice *) &m_logFile );
    kdDebug() << "KDarController::openLogFile()" << endl;
}

void KDarController::populateArchiveTree( KDarConfig *, QListViewItem* directory )
{
    if (libdarWorking)
    {
        return;
    }
    waitForThread( controller::OPEN_THREAD );
    if (theArchive == 0) return;

    //Only populate this item if it is an empty directory
    if ( !directory ) return;
    if ( !directory->firstChild() ) return;
    if ( !( directory->firstChild()->text( 0 ) == "<empty>" ) ) return;
    //Otherwise we have an empty directory that needs to be populated
    currentDirectory = static_cast<kdarListViewItem*> (directory);
    kdDebug() << "KDarContoller::populateArchiveTree() called: creating and starting m_populateTreeThread" << endl;
    m_populateTreeThread = new populateTreeArchiveThread( this, directory );
    m_populateTreeThread->start();
}

void KDarController::restoreArchive( KDarConfig * kdarconfig )
{
    if ( libdarWorking )
    {
        return;
    }
    kdDebug() << "KDarContoller::restoreArchive() called." << endl;
    kdDebug() << "starting create thread." << endl;

    m_restoreThread = new restoreArchiveThread( this, kdarconfig, m_parent->archiveFileView );
    m_restoreThread->start();
    kdDebug() << "started create thread." << endl;
}

void KDarController::testArchive( KDarConfig * kdarconfig )
{
    if (libdarWorking)
    {
        return;
    }
    if (theArchive == 0) return;
    //test the archive
    kdDebug() << "KDarContoller::testArchive() creating and starting m_testThread" << endl;
    m_testThread = new testArchiveThread( this, kdarconfig, m_parent->archiveFileView );
    m_testThread->start();
}

void KDarController::customEvent( QCustomEvent * e )
{
    if ( e->type() == (QEvent::Type) KDar::SETCURSOR )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarSetCursorEvent* sce = (kdarSetCursorEvent*)e;
            kdarSetCursorEvent* newsce = new kdarSetCursorEvent( sce->cursor() );
            QApplication::postEvent( m_parent, newsce );
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::CHECKFILESIZE )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarCheckFileSizeEvent *cfse = (kdarCheckFileSizeEvent*) e;
            kdarCheckFileSizeEvent *newcfse = new kdarCheckFileSizeEvent( cfse->checkFileSizeAction() );
            QApplication::postEvent( m_parent, newcfse );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::PROGRESS )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarProgressEvent *pe = (kdarProgressEvent*) e;
            kdarProgressEvent *newpe = new kdarProgressEvent( pe->command() );
            QApplication::postEvent( m_parent, newpe );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::STATUSBAR )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarStatusBarEvent *se = (kdarStatusBarEvent*) e;
            //Fix this output: There are spaces between lines.
//            QString message = se->message();
//            writeLogMessage( message );
            kdarStatusBarEvent *newse = new kdarStatusBarEvent( se->message(), se->duration() );
            QApplication::postEvent( m_parent, newse );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::PROGRESSDIALOG )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarProgressDialogEvent *pde = (kdarProgressDialogEvent*) e;
            kdarProgressDialogEvent *newpde = new kdarProgressDialogEvent( pde->message(), pde->field() );
            QApplication::postEvent( m_parent, newpde );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::WARNING )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarWarningEvent *we = (kdarWarningEvent*) e;
            QString message = we->message();
            writeLogMessage( message );
            kdarWarningEvent *newwe = new kdarWarningEvent( we->message() );
            QApplication::postEvent( m_parent, newwe );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::TARLISTING )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarTarListingEvent *tle = (kdarTarListingEvent*) e;
            kdarTarListingEvent *newtle = new kdarTarListingEvent( tle->directory(), tle->flag(), tle->perm(), tle->uid(), tle->gid(), tle->size(), tle->date(), tle->filename(), tle->isDir(), tle->hasChildren() );
            QApplication::postEvent( m_parent, newtle );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::USERINTERACTION )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarUserInteractionEvent *uie = (kdarUserInteractionEvent*) e;
            kdarUserInteractionEvent *newuie = new kdarUserInteractionEvent( uie->question() );
            QApplication::postEvent( m_parent, newuie );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::USERINTERACTIONSTRING )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarUserInteractionStringEvent *uise = (kdarUserInteractionStringEvent*) e;
            kdarUserInteractionStringEvent *newuise = new kdarUserInteractionStringEvent( uise->question(), uise->echo() );
            QApplication::postEvent( m_parent, newuise );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::POSTLISTVIEWITEM )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarPostListViewItemEvent *pe = (kdarPostListViewItemEvent*) e;
            kdarPostListViewItemEvent *newpe = new kdarPostListViewItemEvent( pe->text(), pe->clearView() );
            QApplication::postEvent( m_parent, newpe );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::ARCHIVEBROWSERUPDATES )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarArchiveBrowserUpdatesEvent *ae = (kdarArchiveBrowserUpdatesEvent*) e;
            kdarArchiveBrowserUpdatesEvent *newae = new kdarArchiveBrowserUpdatesEvent( ae->command() );
            QApplication::postEvent( m_parent, newae );
        }
        else
        {
            kdDebug() << "KDarController::customEvent(): m_parent isn't right!" << endl;
        }
    }
    if ( e->type() == ( QEvent::Type ) KDar::DELETETHREAD )
    {
        kdarDeleteThreadEvent* dte = (kdarDeleteThreadEvent*)e;
        QThread* thread = dte->thread();
        if ( !thread ) return;
        if ( thread->running() )
        {
            thread->wait();
        }
        delete thread;
        //set the corresponding thread pointer to zero
        if ( thread == m_createThread )
        {
            m_createThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_createThread" << endl;
        }
        if ( thread == m_diffThread )
        {
            m_diffThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_diffThread" << endl;
        }
        if ( thread == m_isolateThread )
        {
            m_isolateThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_isolateThread" << endl;
        }
        if ( thread == m_listThread )
        {
            m_listThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_listThread" << endl;
        }
        if ( thread == m_openThread )
        {
            m_openThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_openThread" << endl;
        }
        if ( thread == m_populateTreeThread )
        {
            m_populateTreeThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_populateTreeThread" << endl;
            //We need to re-enable updates to the archive browser:

        }
        if ( thread == m_restoreThread )
        {
            m_restoreThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_restoreThread" << endl;
        }
        if ( thread == m_testThread )
        {
            m_testThread = 0;
            kdDebug() << "KDarController::customEvent(): deleted m_testThread" << endl;
        }
    }
    if ( e->type() == (QEvent::Type) KDar::CANCELBUTTON )
    {
        if ( m_parent != NULL && m_parent != 0 )
        {
            kdarCancelButtonEvent* cbe = (kdarCancelButtonEvent*)e;
            kdarCancelButtonEvent* newcbe = new kdarCancelButtonEvent( cbe->command() );
            QApplication::postEvent( m_parent, newcbe );
        }
    }
    if ( e->type() == (QEvent::Type) KDar::LOGFILECOMMAND )
    {
        kdarLogFileCommandEvent* lce = (kdarLogFileCommandEvent*)e;
        QString logText = lce->text();
        switch ( (int) lce->command() )
        {
            case kdarLogFileCommandEvent::OPEN:
                openLogFile( logText );
                break;
            case kdarLogFileCommandEvent::CLOSE:
                closeLogFile();
                break;
            case kdarLogFileCommandEvent::WRITEMESSAGE:
                writeLogMessage( logText );
                break;
            case kdarLogFileCommandEvent::FLUSH:
                m_logFile.flush();
            default:
                ;
        }
    }
}

void KDarController::waitForThread( controller::threadType type )
{
    //Check if the given thread type is running, and wait for it to finish
    switch ( type )
    {
        case controller::OPEN_THREAD:
            kdDebug() << "KDarController::waitForThread(): OPEN_THREAD" << endl;
            if ( m_openThread ) m_openThread->wait();
            break;
        case controller::CREATE_THREAD:
            if ( m_createThread ) m_createThread->wait();
            break;
        case controller::RESTORE_THREAD:
            if ( m_restoreThread ) m_restoreThread->wait();
            break;
        default:
            ;
    }
}

bool KDarController::cancelOperation()
{
    bool cancelled = false;

    // Try to cancel a create operation if it is running.
    if ( m_createThread )
    {
        //Cancel the thread
        kdDebug() << "KDarController::cancelOperation(): cancelling m_createThread" << endl;
        cancelled = m_createThread->cancelOperation();
    }
    if ( !cancelled && m_testThread )
    {
        //Cancel the thread
        kdDebug() << "KDarController::cancelOperation(): cancelling m_testThread" << endl;
        cancelled = m_testThread->cancelOperation();
        kdDebug() << "KDarController::cancelOperation(): cancelled is " << cancelled << endl;
    }
    if ( !cancelled && m_restoreThread )
    {
        //Cancel the thread
        kdDebug() << "KDarController::cancelOperation(): cancelling m_restoreThread" << endl;
        cancelled = m_restoreThread->cancelOperation();
    }
    if ( !cancelled && m_diffThread )
    {
        //Cancel the thread
        kdDebug() << "KDarController::cancelOperation(): cancelling m_diffThread" << endl;
        cancelled = m_diffThread->cancelOperation();
    }
    if ( !cancelled && m_isolateThread )
    {
        //Cancel the thread
        kdDebug() << "KDarController::cancelOperation(): cancelling m_isolateThread" << endl;
        cancelled = m_isolateThread->cancelOperation();
    }
    if ( !cancelled && m_openThread )
    {
        //Cancel the thread
        kdDebug() << "KDarController::cancelOperation(): cancelling m_openThread" << endl;
        cancelled = m_openThread->cancelOperation();
    }

    return cancelled;
}

void KDarController::writeLogMessage( QString & message )
{
    QIODevice * device = m_logStream.device();
    if ( device )
    {
        if ( !message.isEmpty() )
        {
            QString msg = message;
            if ( !msg.endsWith( "\n" ) ) msg += "\n";
            kdDebug() << "KDarController::writeLogMessage(): writing " << msg;
            m_logStream << msg;
            m_logFile.flush();
        }
        else
        {
            kdDebug() << "KDarController::writeLogMessage(): message \"" << message << "\" is empty." << endl;

        }
    }
    else
    {
        kdDebug() << "KDarController::writeLogMessage(): m_logStream is not open." << endl;
        kdDebug() << "message was " << message << endl;
    }
}

void KDarController::setParent( void *parent )
{
    kdDebug() << "KDarController::setParent(): setting m_parent." << endl;
    m_parent = static_cast<kdarView*>(parent);
    kdDebug() << "KDarController::setParent(): set m_parent." << endl;
}

bool KDarController::obtainPassword()
{
    kdDebug() << "KDarController::obtainPassword(): called." << endl;
    bool success = true;
    bool askUserForPassword = false;
    bool usingWallet = true;
    if ( m_parent != NULL && m_parent !=0 )
    {
        usingWallet = m_parent->useWallet();
    }
    if ( !m_localWallet || !usingWallet )
    {
        //No wallet
        askUserForPassword = true;
        kdDebug() << "KDarController::obtainPassword(): not using wallet." << endl;
    }
    else
    {
        if ( !m_localWallet->hasFolder( KDARKWALLETFOLDER ) )
        {
            //No password folder. The password folder should have been
            //created in the KDarController constructor if it did not already
            //exist. Don't second guess the reason that is missing. Just ask
            //the user for a password.
            askUserForPassword = true;
            kdDebug() << "KDarController::obtainPassword(): no KDARKWALLETFOLDER." << endl;
        }
        else
        {
            bool isOpen = m_localWallet->isOpen();
            kdDebug() << "KDarController::obtainPassword(): wallet->isOpen() = " << isOpen << endl;
            if ( !m_localWallet->setFolder( KDARKWALLETFOLDER ) )
            {
                //Error, so ask user for password.
                askUserForPassword = true;
                kdDebug() << "KDarController::obtainPassword(): could not set folder: returned " << endl;
            }
            else
            {
                kdDebug() << "KDarController::obtainPassword(): reading password from wallet..." << endl;
                int res = m_localWallet->readPassword( "Archive Password", m_password );
                if ( res == 0 && !m_password.isEmpty() )
                {
                    //kdDebug() << "KDarController::obtainPassword(): password from KWallet: " << m_password << endl;
                }
                else
                {
                    kdDebug() << "KDarController::obtainPassword(): error reading password from wallet." << endl;
                    //No password: ask user if they want to store one in the wallet.
                    QString question = i18n( "Would you like to have the KDE Wallet Manager store your encryption password?" );
                    int ret = KMessageBox::warningYesNo(0, question );
                    if ( ret == KMessageBox::Yes )
                    {
                        //Ask user for new password and store it in the wallet
                        bool changed = changePassword();
                        if ( !changed ) askUserForPassword = true;
                    }
                    else
                    {
                        //set the global config option
                        if ( m_parent != NULL && m_parent != 0 )
                        {
                            m_parent->enableWallet( false );
                        }
                        askUserForPassword = true;
                        kdDebug() << "KDarController::obtainPassword(): user does not want to store password in wallet." << endl;
                    }
                }
            }
        }
    }
    //Ask user for password?
    if ( askUserForPassword )
    {
        kdDebug() << "KDarController::obtainPassword(): asking user for password." << endl;
        int result = KPasswordDialog::Rejected;
        QCString userPassword;
        result = KPasswordDialog::getPassword( userPassword, i18n( "Please enter the password:" ) );
        if ( result == KPasswordDialog::Accepted )
        {
            m_password = ( QString ) userPassword;
        }
        else
        {
            m_password = QString( "" );
            success = false;
        }
    }
    return success;
}

QString KDarController::password()
{
    return m_password;
}

void KDarController::clearPassword()
{
    //Clear the password from memory...Does this actually work?
    m_password = "";
}

bool KDarController::changePassword()
{
    bool success = true;
    //open the wallet if it is not open...
    bool walletIsOpen = true;

    if ( !m_localWallet )
    {
        //openWallet
        //The wallet should already be open, right?
        //if error opening wallet,
        walletIsOpen = false;
        success = false;
    }
    if ( walletIsOpen )
    {
        kdDebug() << "KDarController::changePassword(): asking user for password to set." << endl;
        //Get the password from the user, twice!
        int result = KPasswordDialog::Rejected;
        QCString newPassword;
        result = KPasswordDialog::getNewPassword( newPassword, i18n( "Please enter a new password for encrypting archives:" ) );
        if ( result == KPasswordDialog::Accepted )
        {
            m_password = ( QString ) newPassword;
            //Store the password in the wallet:
            kdDebug() << "KDarController::obtainPassword(): storing password in wallet" << endl;
            int res = m_localWallet->writePassword( "Archive Password", m_password );
            if ( res != 0 )
            {
                kdDebug() << "KDarController::obtainPassword(): error saving password in wallet." << endl;
                //Warn user that the password could not be stored.
                KMessageBox::sorry( 0, i18n( "The KDE Wallet Manager could not store the password." ) );
                success = false;
            }
        }
    }
    return success;
}

void KDarController::setUserResponse( const bool response )
{
    m_userResponse = response;
}

bool KDarController::userResponse()
{
    return m_userResponse;
}

QSemaphore * KDarController::semaphore()
{
    return m_semaphore;
}

bool KDarController::handlesEA() const
{
    return m_handlesEA;
}

bool KDarController::handlesLargefiles() const
{
    return m_handlesLargefiles;
}

bool KDarController::handlesNoDump() const
{
    return m_handlesNoDump;
}

bool KDarController::usesSpecialAlloc() const
{
    return m_usesSpecialAlloc;
}

libdar::U_I KDarController::integerSizeBits() const
{
    return m_integerSizeBits;
}

bool KDarController::isThreadSafe() const
{
    return m_isThreadSafe;
}

bool KDarController::handlesZCompression() const
{
    return m_handlesZCompression;
}

bool KDarController::handlesBZ2Compression() const
{
    return m_handlesBZ2Compression;
}

bool KDarController::handlesStrongCrypto() const
{
    return m_handlesStrongCrypto;
}

#include "kdarcontroller.moc"

