/*
    Copyright (c) 2007 Volker Krause <vkrause@kde.org>

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

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

#include "control.h"
#include "recursivecollectionfilterproxymodel.h"
#include "subscriptionjob_p.h"
#include "subscriptionmodel_p.h"

#include <kdebug.h>
#include <kglobal.h>
#include <ksharedconfig.h>


#include <klocalizedstring.h>

#include <QVBoxLayout>
#include <QHBoxLayout>


#ifndef KDEPIM_MOBILE_UI
#include <klineedit.h>
#include <KPushButton>
#include <krecursivefilterproxymodel.h>
#include <QHeaderView>
#include <QLabel>
#include <QTreeView>
#include <QCheckBox>
#else
#include <kdescendantsproxymodel.h>
#include <QListView>
#include <QSortFilterProxyModel>

class CheckableFilterProxyModel : public QSortFilterProxyModel
{
public:
  CheckableFilterProxyModel( QObject *parent = 0 )
    : QSortFilterProxyModel( parent ) { }

protected:
  /*reimp*/ bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
  {
    QModelIndex sourceIndex = sourceModel()->index( sourceRow, 0, sourceParent );
    return sourceModel()->flags( sourceIndex ) & Qt::ItemIsUserCheckable;
  }
};
#endif

using namespace Akonadi;

/**
 * @internal
 */
class SubscriptionDialog::Private
{
  public:
    Private( SubscriptionDialog *parent ) : q( parent ) {}

    void done()
    {
      SubscriptionJob *job = new SubscriptionJob( q );
      job->subscribe( model->subscribed() );
      job->unsubscribe( model->unsubscribed() );
      connect( job, SIGNAL(result(KJob*)), q, SLOT(subscriptionResult(KJob*)) );
    }

    void subscriptionResult( KJob *job )
    {
      if ( job->error() ) {
        // TODO
        kWarning() << job->errorString();
      }
      q->deleteLater();
    }

    void modelLoaded()
    {
      collectionView->setEnabled( true );
#ifndef KDEPIM_MOBILE_UI
      collectionView->expandAll();
#endif
      q->enableButtonOk( true );
    }
    void slotSetPattern(const QString &text)
    {
      filterRecursiveCollectionFilter->setSearchPattern( text );
#ifndef KDEPIM_MOBILE_UI
      collectionView->expandAll();
#endif
    }
    void slotSetIncludeCheckedOnly(bool checked)
    {
      filterRecursiveCollectionFilter->setIncludeCheckedOnly( checked );
    }

    void writeConfig()
    {
      KConfigGroup group( KGlobal::config(), "SubscriptionDialog" );
      group.writeEntry( "Size", q->size() );
    }

    void readConfig()
    {
      KConfigGroup group( KGlobal::config(), "SubscriptionDialog" );
      const QSize sizeDialog = group.readEntry( "Size", QSize(300,200) );
      if ( sizeDialog.isValid() ) {
         q->resize( sizeDialog );
      }
    }

    void slotUnSubscribe();
    void slotSubscribe();

    SubscriptionDialog* q;
#ifndef KDEPIM_MOBILE_UI
    QTreeView *collectionView;
    KPushButton *subscribe;
    KPushButton *unSubscribe;
#else
    QListView *collectionView;
#endif
    SubscriptionModel* model;
    RecursiveCollectionFilterProxyModel *filterRecursiveCollectionFilter;

};

void SubscriptionDialog::Private::slotSubscribe()
{
#ifndef KDEPIM_MOBILE_UI
  QModelIndexList list = collectionView->selectionModel()->selectedIndexes();
  foreach (const QModelIndex& index, list) {
      model->setData(index, Qt::Checked, Qt::CheckStateRole);
  }
  collectionView->setFocus();
#endif
}

void SubscriptionDialog::Private::slotUnSubscribe()
{
#ifndef KDEPIM_MOBILE_UI
    QModelIndexList list = collectionView->selectionModel()->selectedIndexes();
    foreach (const QModelIndex& index, list) {
       model->setData(index, Qt::Unchecked, Qt::CheckStateRole);
    }
    collectionView->setFocus();
#endif
}

SubscriptionDialog::SubscriptionDialog(QWidget * parent) :
    KDialog( parent ),
    d( new Private( this ) )
{
  init( QStringList() );
}

SubscriptionDialog::SubscriptionDialog(const QStringList& mimetypes, QWidget * parent) :
    KDialog( parent ),
    d( new Private( this ) )
{
  init( mimetypes );
}

void SubscriptionDialog::showHiddenCollection(bool showHidden)
{
  d->model->showHiddenCollection(showHidden);
}

void SubscriptionDialog::init( const QStringList &mimetypes )
{
  enableButtonOk( false );
  setCaption( i18n( "Local Subscriptions" ) );
  QWidget *mainWidget = new QWidget( this );
  QVBoxLayout *mainLayout = new QVBoxLayout;
  mainWidget->setLayout( mainLayout );
  setMainWidget( mainWidget );

  d->model = new SubscriptionModel( this );

#ifndef KDEPIM_MOBILE_UI
  d->filterRecursiveCollectionFilter
      = new Akonadi::RecursiveCollectionFilterProxyModel( this );
  d->filterRecursiveCollectionFilter->setDynamicSortFilter( true );
  d->filterRecursiveCollectionFilter->setSourceModel( d->model );
  d->filterRecursiveCollectionFilter->setFilterCaseSensitivity( Qt::CaseInsensitive );
  if ( !mimetypes.isEmpty() ) {
    d->filterRecursiveCollectionFilter->addContentMimeTypeInclusionFilters( mimetypes );
  }

  d->collectionView = new QTreeView( mainWidget );
  d->collectionView->setEditTriggers( QAbstractItemView::NoEditTriggers );
  d->collectionView->header()->hide();
  d->collectionView->setModel( d->filterRecursiveCollectionFilter );
  d->collectionView->setSelectionMode(QAbstractItemView::ExtendedSelection);

  QHBoxLayout *filterBarLayout = new QHBoxLayout;

  filterBarLayout->addWidget( new QLabel( i18n( "Search:" ) ) );

  KLineEdit *lineEdit = new KLineEdit( mainWidget );
  lineEdit->setClearButtonShown(true);
  lineEdit->setFocus();
  connect( lineEdit, SIGNAL(textChanged(QString)),
           this, SLOT(slotSetPattern(QString)) );
  filterBarLayout->addWidget( lineEdit );
  QCheckBox *checkBox = new QCheckBox( i18n("Subscribed only"), mainWidget );
  connect( checkBox, SIGNAL(clicked(bool)),
           this, SLOT(slotSetIncludeCheckedOnly(bool)) );
  filterBarLayout->addWidget( checkBox );

  QHBoxLayout *hboxLayout = new QHBoxLayout;
  hboxLayout->addWidget( d->collectionView );

  QVBoxLayout *subscribeButtonLayout = new QVBoxLayout;
  d->subscribe = new KPushButton(i18n("Subscribe"));
  subscribeButtonLayout->addWidget(d->subscribe);
  connect(d->subscribe,SIGNAL(clicked()),this,SLOT(slotSubscribe()));

  d->unSubscribe = new KPushButton(i18n("Unsubscribe"));
  subscribeButtonLayout->addWidget(d->unSubscribe);
  connect(d->unSubscribe,SIGNAL(clicked()),this,SLOT(slotUnSubscribe()));
  subscribeButtonLayout->addItem( new QSpacerItem( 5, 5, QSizePolicy::Minimum, QSizePolicy::Expanding ) );

  hboxLayout->addLayout(subscribeButtonLayout);

  mainLayout->addLayout(filterBarLayout);
  mainLayout->addLayout(hboxLayout);

#else

  d->filterRecursiveCollectionFilter
      = new Akonadi::RecursiveCollectionFilterProxyModel( this );
  if ( !mimetypes.isEmpty() )
    d->filterRecursiveCollectionFilter->addContentMimeTypeInclusionFilters( mimetypes );

  d->filterRecursiveCollectionFilter->setSourceModel( d->model );

  KDescendantsProxyModel *flatModel = new KDescendantsProxyModel( this );
  flatModel->setDisplayAncestorData( true );
  flatModel->setAncestorSeparator( QLatin1String( "/" ) );
  flatModel->setSourceModel( d->filterRecursiveCollectionFilter );

  CheckableFilterProxyModel *checkableModel = new CheckableFilterProxyModel( this );
  checkableModel->setSourceModel( flatModel );

  d->collectionView = new QListView( mainWidget );

  d->collectionView->setModel( checkableModel );
  mainLayout->addWidget( d->collectionView );
#endif

  connect( d->model, SIGNAL(loaded()), SLOT(modelLoaded()) );
  connect( this, SIGNAL(okClicked()), SLOT(done()) );
  connect( this, SIGNAL(cancelClicked()), SLOT(deleteLater()) );
  Control::widgetNeedsAkonadi( mainWidget );
  d->readConfig();
}

SubscriptionDialog::~SubscriptionDialog()
{
  d->writeConfig();
  delete d;
}

#include "moc_subscriptiondialog_p.cpp"
