/*****************************************************************

   Copyright (c) 2006 Stephan Binner <binner@kde.org>

   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.

   This program 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
    General Public License for more details.

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

******************************************************************/

#include "indexing.h"
#include "ui_select_privacy_resource.h"

#include <qdom.h>
#include <q3groupbox.h>
#include <QLabel>
#include <QLayout>
#include <QRadioButton>
//Added by qt3to4:
#include <QHBoxLayout>
#include <Q3GridLayout>
#include <QVBoxLayout>
#include <QTextStream>
#include <kconfig.h>
#include <kdialog.h>
#include <kdirselectdialog.h>
#include <kfile.h>
#include <klocale.h>
#include <kpushbutton.h>
#include <klineedit.h>
#include <kmessagebox.h>
#include <kurl.h>
#include <kurlrequester.h>

KCMBeagleIndexing::KCMBeagleIndexing(const KComponentData &inst, QWidget *parent)
    : KCModule(inst, parent)
{
    QVBoxLayout* top_layout = new QVBoxLayout( this, KDialog::spacingHint() );

    // General
    Q3GroupBox* gb_general = new Q3GroupBox(0, Qt::Vertical, i18n("General"), this);
    top_layout->addWidget(gb_general);
    gb_general->setFlat(true);
    QVBoxLayout* gb_general_layout = new QVBoxLayout( gb_general->layout(), KDialog::spacingHint() );

    startBeagle = new QCheckBox(i18n("Start Beagle indexing service automatically"), gb_general);
    gb_general_layout->addWidget( startBeagle);

    indexOnBattery = new QCheckBox(i18n("Index data while on battery power"), gb_general);
    gb_general_layout->addWidget( indexOnBattery );

    // Index
    Q3GroupBox* gb_index = new Q3GroupBox(0, Qt::Vertical, i18n("Index"), this);
    top_layout->addWidget(gb_index);
    gb_index->setFlat(true);
    QVBoxLayout* gb_index_layout = new QVBoxLayout( gb_index->layout(), KDialog::spacingHint() );

    QHBoxLayout* qh_index = new QHBoxLayout(gb_index_layout);
    indexHome = new QCheckBox(i18n("Index my home folder"), gb_index);
    qh_index->addWidget( indexHome );
    qh_index->addStretch(1);

    QLabel* label_index = new QLabel(i18n( "Add any additional folder to be included for indexing." ), gb_index);
    gb_index_layout->addWidget(label_index);

    Q3GridLayout* grid_index = new Q3GridLayout( gb_index_layout, 1, 1, KDialog::spacingHint());

    index_list = new K3ListView( gb_index );
    index_list->addColumn( i18n( "Name" ) );
    index_list->setResizeMode( K3ListView::LastColumn );
    index_list->setFullWidth( true );
    grid_index->addMultiCellWidget( index_list, 0, 2, 0, 0 );
    label_index->setBuddy(index_list);

    QPushButton* add_index = new QPushButton( i18n("Add..."), gb_index );
    grid_index->addWidget( add_index, 0, 1 );

    remove_index = new QPushButton( i18n("Remove"), gb_index );
    remove_index->setEnabled(false);
    grid_index->addWidget( remove_index, 1, 1 );

    QSpacerItem* index_spacer = new QSpacerItem( 20, 30, QSizePolicy::Minimum, QSizePolicy::Preferred );
    grid_index->addItem( index_spacer, 2, 1 );

    connect( add_index, SIGNAL( clicked() ), this, SLOT( slotAddSearch() ) );
    connect( remove_index, SIGNAL( clicked() ), this, SLOT( slotRemoveSearch() ) );
    connect( index_list, SIGNAL( selectionChanged(Q3ListViewItem*) ), this, SLOT( slotSearchSelectionChanged(Q3ListViewItem*) ) );

    // Privacy
    Q3GroupBox* gb_privacy = new Q3GroupBox(0, Qt::Vertical, i18n("Privacy"), this);
    top_layout->addWidget(gb_privacy);
    gb_privacy->setFlat(true);
    QVBoxLayout* gb_privacy_layout = new QVBoxLayout( gb_privacy->layout(), KDialog::spacingHint() );

    QLabel* label_privacy = new QLabel(i18n( "Specify any resource, such as folder or pattern, you wish to exclude from indexing." ), gb_privacy);
    gb_privacy_layout->addWidget(label_privacy);

    Q3GridLayout* grid_privacy = new Q3GridLayout( gb_privacy_layout, 1, 1, KDialog::spacingHint());

    privacy_list = new K3ListView( gb_privacy );
    privacy_list->addColumn( i18n( "Type" ) );
    privacy_list->addColumn( i18n( "Name" ) );
    privacy_list->setResizeMode( K3ListView::LastColumn );
    privacy_list->setFullWidth( true );
    privacy_list->setAllColumnsShowFocus( true );
    grid_privacy->addMultiCellWidget( privacy_list, 0, 2, 0, 0 );
    label_privacy->setBuddy(privacy_list);

    QPushButton* add_privacy = new QPushButton( i18n("Add..."), gb_privacy );
    grid_privacy->addWidget( add_privacy, 0, 1 );

    remove_privacy = new QPushButton( i18n("Remove"), gb_privacy );
    remove_privacy->setEnabled(false);
    grid_privacy->addWidget( remove_privacy, 1, 1 );

    QSpacerItem* privacy_spacer = new QSpacerItem( 20, 30, QSizePolicy::Minimum, QSizePolicy::Preferred );
    grid_privacy->addItem( privacy_spacer, 2, 1 );

    connect( add_privacy, SIGNAL( clicked() ), this, SLOT( slotAddPrivacy() ) );
    connect( remove_privacy, SIGNAL( clicked() ), this, SLOT( slotRemovePrivacy() ) );
    connect( privacy_list, SIGNAL( selectionChanged(Q3ListViewItem*) ), this, SLOT( slotPrivacySelectionChanged(Q3ListViewItem*) ) );

    // Add some spacing at the end
    QWidget *dummy = new QWidget( this );
    top_layout->addWidget(dummy);
    top_layout->setStretchFactor( dummy, 1 );

    load();

    connect(indexOnBattery, SIGNAL(clicked()), SLOT(changedValue()));
    connect(startBeagle, SIGNAL(clicked()), SLOT(changedValue()));
    connect(indexHome, SIGNAL(clicked()), SLOT(changedValue()));
}

KCMBeagleIndexing::~KCMBeagleIndexing()
{
}

void KCMBeagleIndexing::changedValue()
{
    emit changed( true );
}

void KCMBeagleIndexing::load()
{
    load( false );
}

void KCMBeagleIndexing::load( bool useDefaults )
{
    bool _indexHomeDir, _indexOnBattery, _startBeagle;
    QStringList roots, excludeTypes, excludeValues;

    if (useDefaults) {
        _indexHomeDir = true;
        _indexOnBattery = true;
        _startBeagle = true;
    }
    else {
        KConfig *config = new KConfig("kerryrc");
        KConfigGroup group = config->group("Beagle");
        _startBeagle = group.readEntry("AutoStart",true);
        delete config;

        readIndexConfig(_indexHomeDir, _indexOnBattery, roots, excludeTypes, excludeValues);
    }

    indexHome->setChecked(_indexHomeDir);
    indexOnBattery->setChecked(_indexOnBattery);
    startBeagle->setChecked(_startBeagle);

    index_list->clear();
    remove_index->setEnabled(false);
    for ( QStringList::Iterator it = roots.begin(); it != roots.end(); ++it ) {
       new K3ListViewItem(index_list,*it);
    }

    privacy_list->clear();
    remove_privacy->setEnabled(false);
    QStringList::Iterator it_values = excludeValues.begin();
    for ( QStringList::Iterator it_types = excludeTypes.begin(); it_types != excludeTypes.end(); ++it_types ) {
      new K3ListViewItem(privacy_list,*it_types,*it_values);
      it_values++;
    }

    emit changed( useDefaults );
}

void KCMBeagleIndexing::defaults()
{
     load( true );
}

void KCMBeagleIndexing::save()
{
    KConfig *config = new KConfig("kerryrc");
    KConfigGroup group = config->group("Beagle");
    group.writeEntry("AutoStart",startBeagle->isChecked());
    group.sync();


    QStringList roots;
    for (int i=0;i<index_list->childCount();i++)
       roots << index_list->itemAtIndex(i)->text(0);

    QStringList excludeTypes;
     for (int i=0;i<privacy_list->childCount();i++)
       excludeTypes << privacy_list->itemAtIndex(i)->text(0);

    QStringList excludeValues;
    for (int i=0;i<privacy_list->childCount();i++)
       excludeValues << privacy_list->itemAtIndex(i)->text(1);

    saveIndexConfig(indexHome->isChecked(), indexOnBattery->isChecked(), roots, excludeTypes, excludeValues);
}

void KCMBeagleIndexing::slotAddSearch()
{
    KUrl path = KDirSelectDialog::selectDirectory( QDir::home().absPath(), true, this, i18n("Select Folder"));
    new K3ListViewItem(index_list,path.path());
    changedValue();
}

void KCMBeagleIndexing::slotSearchSelectionChanged(Q3ListViewItem* item)
{
    remove_index->setEnabled( item );
}

void KCMBeagleIndexing::slotRemoveSearch()
{
    Q3ListViewItem *item = index_list->currentItem();
    if (item &&
      KMessageBox::warningContinueCancel(this, i18n("<qt>Do you really want to remove this folder from the list of folders to be included for indexing?</qt>"),i18n("Remove Folder"),KStandardGuiItem::del()) == KMessageBox::Continue)
    {
      delete item;
      remove_index->setEnabled( index_list->childCount() );
      changedValue();
    }
}

void KCMBeagleIndexing::slotAddPrivacy()
{
/*    KDialog dlg();
    dlg.setCaption(i18n("Add Resource"));
//this, 0, true, , KDialog::Ok | KDialog::Cancel);
    AddPrivacyResource w(&dlg);
    dlg.setMainWidget(&w);
    connect(w.radioButtonFolder, SIGNAL(toggled(bool)), w.folderRequester, SLOT(setEnabled(bool)));
    connect(w.radioButtonFolder, SIGNAL(toggled(bool)), w.patternEdit, SLOT(setDisabled(bool)));
    connect(w.radioButtonPattern, SIGNAL(toggled(bool)), w.patternEdit, SLOT(setEnabled(bool)));
    connect(w.radioButtonPattern, SIGNAL(toggled(bool)), w.folderRequester, SLOT(setDisabled(bool)));
    w.folderRequester->setCaption(i18n("Select Folder"));
    w.radioButtonFolder->setChecked(true);
    w.folderRequester->setMode(KFile::Directory | KFile::LocalOnly);
    if (dlg.exec())
    {
       if ( w.radioButtonFolder->isChecked()) {
         QString path = w.folderRequester->lineEdit()->text();
         if (!path.isEmpty()) {
           if (path.startsWith("~"))
             path.replace('~', QDir::homePath());
           new K3ListViewItem(privacy_list,"Path",path);
         }
       }
       else
         if (!w.patternEdit->text().isEmpty())
           new K3ListViewItem(privacy_list,"Pattern",w.patternEdit->text());
       changedValue();
    }
*/
}

void KCMBeagleIndexing::slotRemovePrivacy()
{
    Q3ListViewItem *item = privacy_list->currentItem();
    if (item &&
      KMessageBox::warningContinueCancel(this, i18n("<qt>Do you really want to remove this item from the list of data to be excluded from indexing?</qt>"),i18n("Remove Item"),KStandardGuiItem::del()) == KMessageBox::Continue)
    {
      delete item;
      remove_privacy->setEnabled( privacy_list->childCount() );
      changedValue();
    }
}

void KCMBeagleIndexing::slotPrivacySelectionChanged(Q3ListViewItem* item)
{
    remove_privacy->setEnabled( item );
}

void KCMBeagleIndexing::readIndexConfig(bool &indexHomeDir, bool &indexOnBattery, QStringList &roots, QStringList &excludeTypes, QStringList &excludeValues)
{
    indexHomeDir = true;
    indexOnBattery = true;
    roots.clear();
    excludeTypes.clear();
    excludeValues.clear();

    QFile file( QDir::home().absPath()+"/.beagle/config/indexing.xml" );
    if ( !file.open( QIODevice::ReadOnly ) )
        return;

    QDomDocument doc( "mydocument" );
    if ( !doc.setContent( &file ) ) {
        file.close();
        return;
    }
    file.close();

    QDomElement docElem = doc.documentElement();

    QDomNode n = docElem.firstChild();
    while( !n.isNull() ) {
        QDomElement e = n.toElement();
        if( !e.isNull() ) {
            if (e.tagName()=="IndexHomeDir")
               indexHomeDir = e.text()=="true";
            if (e.tagName()=="IndexOnBattery")
               indexOnBattery = e.text()=="true";
            else if (e.tagName()=="Roots") {
               QDomNode ro = n.firstChild();
               while( !ro.isNull() ) {
                  QDomElement exel = ro.toElement();
                  if( !exel.isNull() )
                    roots << exel.text();
                  ro = ro.nextSibling();
                }
            }
            else if (e.tagName()=="Excludes") {
                QDomNode ex = n.firstChild();
                while( !ex.isNull() ) {
                  QDomElement exel = ex.toElement();
                  if( !exel.isNull() ) {
                    excludeTypes << exel.attribute("Type");
		    excludeValues << exel.attribute("Value");
                  }
                  ex = ex.nextSibling();
                }
            }
        }
        n = n.nextSibling();
    }
}

bool KCMBeagleIndexing::saveIndexConfig(bool indexHomeDir, bool indexOnBattery, QStringList roots, QStringList excludeTypes, QStringList excludeValues)
{
  QDir beagleDir(QDir::home().absPath()+"/.beagle");
  if (!beagleDir.exists())
    beagleDir.mkdir(QDir::home().absPath()+"/.beagle");

  QDir beagleConfigDir(QDir::home().absPath()+"/.beagle/config");
  if (!beagleConfigDir.exists())
    beagleConfigDir.mkdir(QDir::home().absPath()+"/.beagle/config");

  QFile configFile( QDir::home().absPath()+"/.beagle/config/indexing.xml" );
  if ( !configFile.open( QIODevice::WriteOnly ) )
        return false;

  QDomDocument doc( QString::null );
  doc.appendChild( doc.createProcessingInstruction(
                   "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );

  QDomElement root = doc.createElement( "IndexingConfig" );
  root.setAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
  root.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
  doc.appendChild( root );

  QDomElement rootselement = doc.createElement( "Roots" );
  root.appendChild(rootselement);

  for ( QStringList::Iterator it = roots.begin(); it != roots.end(); ++it ) {
    QDomElement tag = doc.createElement( "Root" );
    rootselement.appendChild( tag );

    QDomText t = doc.createTextNode( *it );
    tag.appendChild( t );
  }

  QDomElement tag = doc.createElement( "IndexHomeDir" );
  root.appendChild( tag );

  QDomText t = doc.createTextNode( indexHomeDir ? "true" : "false" );
  tag.appendChild( t );

  tag = doc.createElement( "IndexOnBattery" );
  root.appendChild( tag );

  t = doc.createTextNode( indexOnBattery ? "true" : "false" );
  tag.appendChild( t );

  QDomElement excludeselement = doc.createElement( "Excludes" );
  root.appendChild(excludeselement);

  QStringList::Iterator it_types = excludeTypes.begin();
  for ( QStringList::Iterator it = excludeValues.begin(); it != excludeValues.end(); ++it ) {
    QDomElement t = doc.createElement( "ExcludeItem" );
    t.setAttribute("Type", *it_types);
    t.setAttribute("Value", *it);
    excludeselement.appendChild( t );

    ++it_types;
  }

  QTextStream stream( &configFile );
  stream << doc.toString();
  configFile.close();

  return true;
}

#include "indexing.moc"
