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

   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 "select_privacy_resource.h"

#include <tqdom.h>
#include <tqgroupbox.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqradiobutton.h>
#include <tdeconfig.h>
#include <kdialog.h>
#include <kdirselectdialog.h>
#include <tdefile.h>
#include <tdelocale.h>
#include <kpushbutton.h>
#include <klineedit.h>
#include <tdemessagebox.h>
#include <kurl.h>
#include <kurlrequester.h>

KCMBeagleIndexing::KCMBeagleIndexing(TQWidget *parent, const char * )
    : TDECModule(parent, "kcmbeagleindexing")
{
    TQVBoxLayout* top_layout = new TQVBoxLayout( this, KDialog::spacingHint() );

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

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

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

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

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

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

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

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

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

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

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

    connect( add_index, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAddSearch() ) );
    connect( remove_index, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemoveSearch() ) );
    connect( index_list, TQT_SIGNAL( selectionChanged(TQListViewItem*) ), this, TQT_SLOT( slotSearchSelectionChanged(TQListViewItem*) ) );

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

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

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

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

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

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

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

    connect( add_privacy, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAddPrivacy() ) );
    connect( remove_privacy, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotRemovePrivacy() ) );
    connect( privacy_list, TQT_SIGNAL( selectionChanged(TQListViewItem*) ), this, TQT_SLOT( slotPrivacySelectionChanged(TQListViewItem*) ) );

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

    load();

    connect(indexOnBattery, TQT_SIGNAL(clicked()), TQT_SLOT(changedValue()));
    connect(startBeagle, TQT_SIGNAL(clicked()), TQT_SLOT(changedValue()));
    connect(indexHome, TQT_SIGNAL(clicked()), TQT_SLOT(changedValue()));
}

KCMBeagleIndexing::~KCMBeagleIndexing()
{
}

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

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

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

    if (useDefaults) {
        _indexHomeDir = true;
        _indexOnBattery = true;
        _startBeagle = true;
    }
    else {
        TDEConfig *config = new TDEConfig("kerryrc");
        config->setGroup("Beagle");
        _startBeagle = config->readBoolEntry("AutoStart",false);
        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 ( TQStringList::Iterator it = roots.begin(); it != roots.end(); ++it ) {
       new TDEListViewItem(index_list,*it);
    }

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

    emit changed( useDefaults );
}

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

void KCMBeagleIndexing::save()
{
    TDEConfig *config = new TDEConfig("kerryrc");
    config->setGroup("Beagle");
    config->writeEntry("AutoStart",startBeagle->isChecked());
    config->sync();
    delete config;


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

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

    TQStringList 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( TQDir::home().absPath(), true, this, i18n("Select Folder"));
    new TDEListViewItem(index_list,path.path());
    changedValue();
}

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

void KCMBeagleIndexing::slotRemoveSearch()
{
    TQListViewItem *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"),KStdGuiItem::del()) == KMessageBox::Continue)
    {
      delete item;
      remove_index->setEnabled( index_list->childCount() );
      changedValue();
    }
}

void KCMBeagleIndexing::slotAddPrivacy()
{
    KDialogBase dlg(this, 0, true, i18n("Add Resource"), KDialogBase::Ok | KDialogBase::Cancel);
    AddPrivacyResource w(&dlg);
    dlg.setMainWidget(&w);
    connect(w.radioButtonFolder, TQT_SIGNAL(toggled(bool)), w.folderRequester, TQT_SLOT(setEnabled(bool)));
    connect(w.radioButtonFolder, TQT_SIGNAL(toggled(bool)), w.patternEdit, TQT_SLOT(setDisabled(bool)));
    connect(w.radioButtonPattern, TQT_SIGNAL(toggled(bool)), w.patternEdit, TQT_SLOT(setEnabled(bool)));
    connect(w.radioButtonPattern, TQT_SIGNAL(toggled(bool)), w.folderRequester, TQT_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()) {
         if (!w.folderRequester->lineEdit()->text().isEmpty())
           new TDEListViewItem(privacy_list,"Path",w.folderRequester->lineEdit()->text());
       }
       else
         if (!w.patternEdit->text().isEmpty())
           new TDEListViewItem(privacy_list,"Pattern",w.patternEdit->text());
       changedValue();
    }
}

void KCMBeagleIndexing::slotRemovePrivacy()
{
    TQListViewItem *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"),KStdGuiItem::del()) == KMessageBox::Continue)
    {
      delete item;
      remove_privacy->setEnabled( privacy_list->childCount() );
      changedValue();
    }
}

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

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

    TQFile file( TQDir::home().absPath()+"/.beagle/config/indexing.xml" );
    if ( !file.open( IO_ReadOnly ) )
        return;

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

    TQDomElement docElem = doc.documentElement();

    TQDomNode n = docElem.firstChild();
    while( !n.isNull() ) {
        TQDomElement 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") {
               TQDomNode ro = n.firstChild();
               while( !ro.isNull() ) {
                  TQDomElement exel = ro.toElement();
                  if( !exel.isNull() )
                    roots << exel.text();
                  ro = ro.nextSibling();
                }
            }
            else if (e.tagName()=="Excludes") {
                TQDomNode ex = n.firstChild();
                while( !ex.isNull() ) {
                  TQDomElement 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, TQStringList roots, TQStringList excludeTypes, TQStringList excludeValues)
{
  TQDir beagleDir(TQDir::home().absPath()+"/.beagle");
  if (!beagleDir.exists())
    beagleDir.mkdir(TQDir::home().absPath()+"/.beagle");

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

  TQFile configFile( TQDir::home().absPath()+"/.beagle/config/indexing.xml" );
  if ( !configFile.open( IO_WriteOnly ) )
        return false;

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

  TQDomElement 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 );

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

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

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

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

  TQDomText 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 );

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

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

    ++it_types;
  }

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

  return true;
}

#include "indexing.moc"
