/* This file is part of the KDE Project
   Copyright (c) 2007-2010 Sebastian Trueg <trueg@kde.org>
   Copyright (c) 2012-2014 Vishesh Handa <me@vhanda.in>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "kcm.h"
#include "baloodefaults.h"

#include <KPluginFactory>
#include <KPluginLoader>
#include <KAboutData>
#include <KSharedConfig>
#include <KDirWatch>
#include <KDebug>
#include <KStandardDirs>

#include <QPushButton>
#include <QMessageBox>
#include <QDir>
#include <QProcess>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusPendingCall>
#include <QDBusServiceWatcher>

K_PLUGIN_FACTORY(BalooConfigModuleFactory, registerPlugin<Baloo::ServerConfigModule>();)
K_EXPORT_PLUGIN(BalooConfigModuleFactory("kcm_baloofileadv"))


namespace
{
QStringList defaultFolders()
{
    return QStringList() << QDir::homePath();
}

}

using namespace Baloo;

ServerConfigModule::ServerConfigModule(QWidget* parent, const QVariantList& args)
    : KCModule(BalooConfigModuleFactory::componentData(), parent, args),
    m_FileIndexer(NULL)
{
    KAboutData* about = new KAboutData(
        "kcm_baloofileadv", "kcm_baloofileadv", ki18n("Configure Desktop Search"),
        KDE_VERSION_STRING, KLocalizedString(), KAboutData::License_GPL,
        ki18n("Copyright 2007-2010 Sebastian Trüg"));
    about->addAuthor(ki18n("Sebastian Trüg"), KLocalizedString(), "trueg@kde.org");
    about->addAuthor(ki18n("Vishesh Handa"), KLocalizedString(), "vhanda@kde.org");
    setAboutData(about);
    setButtons(Help | Apply | Default);

    setupUi(this);

    m_indexFolderSelectionDialog = new IndexFolderSelectionDialog(this);

    // Service Watcher
    QDBusServiceWatcher * watcher = new QDBusServiceWatcher( this );
    watcher->addWatchedService( QLatin1String("org.kde.baloo.file") );
    watcher->setConnection( QDBusConnection::sessionBus() );
    watcher->setWatchMode( QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration );

    connect( watcher, SIGNAL( serviceRegistered(const QString&) ),
              this, SLOT( slotServiceRegistered(const QString& ) ) );
    connect( watcher, SIGNAL( serviceUnregistered(const QString&) ),
              this, SLOT( slotServiceUnregistered(const QString& ) ) );

    // Signals
    connect(m_CustomiseFolders, SIGNAL(clicked(bool)), SLOT(customiseFoldersClicked()));
    connect(cbEnableFileIndexer, SIGNAL(stateChanged(int)), SLOT(slotEnableFileIndexerStateChanged()));
    connect(bnControlFileIndexer, SIGNAL(clicked(bool)), SLOT(slotControlFileIndexerClicked()));
    connect(m_editExcludeFilters, SIGNAL(changed()), this, SLOT(changed()));
    connect(m_editMimeTypeExcludes, SIGNAL(changed()), this, SLOT(changed()));

    getInterfaces();
    updateFileIndexerStatus();
}


ServerConfigModule::~ServerConfigModule()
{
  delete m_FileIndexer;
}


void ServerConfigModule::load()
{
    // File indexer settings
    KConfig config("baloofilerc");

    // Basic Settings
    KConfigGroup basic = config.group("Basic Settings");
    cbEnableFileIndexer->setChecked(basic.readEntry<bool>("Indexing-Enabled", true));

    // General Settings
    KConfigGroup general = config.group("General");

    QStringList includeFolders = general.readPathEntry("folders", defaultFolders());
    QStringList excludeFolders = general.readPathEntry("exclude folders", QStringList());
    m_indexFolderSelectionDialog->setFolders(includeFolders, excludeFolders);
    m_indexFolderSelectionDialog->setIndexHiddenFolders(general.readEntry( "index hidden folders", false ));

    // File/Folder Filters
    setExcludeFilters( general.readPathEntry( "exclude filters", BalooDefaults::defaultExcludeFilterList() ) );

    // Mime Filters
    setExcludeMimeTypes( general.readPathEntry( "exclude mimetypes", BalooDefaults::defaultExcludeMimetypes() ) );


    loadDisplay();

    // All values loaded -> no changes
    Q_EMIT changed(false);
}


void ServerConfigModule::save()
{
    QStringList includeFolders = m_indexFolderSelectionDialog->includeFolders();
    QStringList excludeFolders = m_indexFolderSelectionDialog->excludeFolders();

    // Change the settings
    KConfig config("baloofilerc");
    KConfigGroup basicSettings = config.group("Basic Settings");

    bool indexingEnabled = cbEnableFileIndexer->isChecked();
    basicSettings.writeEntry("Indexing-Enabled", indexingEnabled);

    // General Settings
    KConfigGroup general = config.group("General");
    general.writePathEntry("folders", includeFolders);
    general.writePathEntry("exclude folders", excludeFolders);
    general.writeEntry( "index hidden folders", m_indexFolderSelectionDialog->indexHiddenFolders() );

    // File/Folder Filters
    general.writePathEntry( "exclude filters", excludeFilters() );

    // Mime Filters
    general.writePathEntry( "exclude mimetypes", excludeMimeTypes() );


    // Start Baloo
    if (indexingEnabled) {
        const QString exe = KStandardDirs::findExe(QLatin1String("baloo_file"));
        QProcess::startDetached(exe);
    }
    else {
        QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.kde.baloo.file"),
                                                              QLatin1String("/indexer"),
                                                              QLatin1String("org.kde.baloo.file"),
                                                              QLatin1String("quit"));

        QDBusConnection::sessionBus().asyncCall(message);
    }

    // Start cleaner
    const QString exe = KStandardDirs::findExe(QLatin1String("baloo_file_cleaner"));
    QProcess::startDetached(exe);

    // all values saved -> no changes
    Q_EMIT changed(false);
}


void ServerConfigModule::defaults()
{
    m_indexFolderSelectionDialog->setFolders(defaultFolders(), QStringList());
    m_indexFolderSelectionDialog->setIndexHiddenFolders( false );
    cbEnableFileIndexer->setChecked(true);
    setExcludeFilters( BalooDefaults::defaultExcludeFilterList() );
    setExcludeMimeTypes ( BalooDefaults::defaultExcludeMimetypes() );
    loadDisplay();
    Q_EMIT changed(true);
}

void ServerConfigModule::loadDisplay()
{
    lbInclude->clear();
    lbInclude->addItems(m_indexFolderSelectionDialog->includeFolders());
    lbExclude->clear();
    lbExclude->addItems(m_indexFolderSelectionDialog->excludeFolders());
}

void ServerConfigModule::slotEnableFileIndexerStateChanged()
{
  updateFileIndexerStatus();
  changed();
}

void ServerConfigModule::customiseFoldersClicked()
{
    KConfig config("baloofilerc");
    KConfigGroup group = config.group("General");

    const QStringList oldIncludeFolders = m_indexFolderSelectionDialog->includeFolders();
    const QStringList oldExcludeFolders = m_indexFolderSelectionDialog->excludeFolders();
    const bool oldIndexHidden = m_indexFolderSelectionDialog->indexHiddenFolders();

    if ( m_indexFolderSelectionDialog->exec() ) {
        loadDisplay();
        changed();
    }
    else {
        // revert to previous settings
        m_indexFolderSelectionDialog->setFolders( oldIncludeFolders, oldExcludeFolders );
        m_indexFolderSelectionDialog->setIndexHiddenFolders( oldIndexHidden );
    }
}

void ServerConfigModule::slotServiceRegistered(const QString& serviceName)
{
    Q_UNUSED(serviceName)

    getInterfaces();
}

void ServerConfigModule::slotServiceUnregistered(const QString& serviceName)
{
    Q_UNUSED(serviceName)

    getInterfaces();
}

void ServerConfigModule::getInterfaces()
{
    delete m_FileIndexer;

    m_FileIndexer = new org::kde::baloo::file("org.kde.baloo.file", "/indexer", QDBusConnection::sessionBus());
    connect(m_FileIndexer, SIGNAL(statusChanged()), SLOT(updateFileIndexerStatus()));
    updateFileIndexerStatus();
}

void ServerConfigModule::updateFileIndexerStatus()
{
    if ( m_FileIndexer && m_FileIndexer->isValid() )
    {
      bnControlFileIndexer->setEnabled(true);
        if (m_FileIndexer->isSuspended() ) {
          lbFileIndexerStatus->setText( i18nc( "@info:status", "Desktop indexing services are suspended" ) );
          bnControlFileIndexer->setText( i18nc( "@info:status", "Resume" ) );
        }
        else {
          lbFileIndexerStatus->setText( i18nc( "@info:status", "Desktop indexing services are running" ) );
          bnControlFileIndexer->setText( i18nc( "@info:status", "Suspend" ) );
        }
    }
    else {
        lbFileIndexerStatus->setText( i18nc( "@info:status", "Desktop indexing services are stopped" ) );
        bnControlFileIndexer->setText( i18nc( "@info:status", "Start" ) );
        if (cbEnableFileIndexer->isChecked())
        {
          bnControlFileIndexer->setDisabled(false);
        }
        else
          bnControlFileIndexer->setDisabled(true);
    }

}

void ServerConfigModule::slotControlFileIndexerClicked()
{
    if (m_FileIndexer && m_FileIndexer->isValid())
    {
        if (m_FileIndexer->isSuspended())
            m_FileIndexer->resume();
        else
            m_FileIndexer->suspend();
    }
    else {
      if (cbEnableFileIndexer->isChecked())
      {
    // Change the settings
          KConfig config("baloofilerc");
          KConfigGroup basicSettings = config.group("Basic Settings");

          basicSettings.writeEntry("Indexing-Enabled", true);

          const QString exe = KStandardDirs::findExe(QLatin1String("baloo_file"));
          QProcess::startDetached(exe);
      }
    }
}

////////////////////////////////////////
// File Filters

void ServerConfigModule::setExcludeFilters(const QStringList& filters)
{
    m_editExcludeFilters->setItems( filters );
}

QStringList ServerConfigModule::excludeFilters()
{
    return m_editExcludeFilters->items();
}

void ServerConfigModule::setExcludeMimeTypes(const QStringList& mimetypes)
{
    m_editMimeTypeExcludes->setItems( mimetypes );

}

QStringList ServerConfigModule::excludeMimeTypes()
{
    return m_editMimeTypeExcludes->items();
}


#include "kcm.moc"
