/*
    Copyright (c) 2008 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 "collectionpropertiesdialog.h"

#include "cachepolicy.h"
#include "cachepolicypage.h"
#include "collection.h"
#include "collectiongeneralpropertiespage_p.h"
#include "collectionmodifyjob.h"

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

#include <QBoxLayout>

using namespace Akonadi;

/**
 * @internal
 */
class CollectionPropertiesDialog::Private
{
  public:
    Private( CollectionPropertiesDialog *parent, const Akonadi::Collection &collection, const QStringList &pageNames );

    void init();

    static void registerBuiltinPages();

    void save()
    {
      for ( int i = 0; i < mTabWidget->count(); ++i ) {
        CollectionPropertiesPage *page = static_cast<CollectionPropertiesPage*>( mTabWidget->widget( i ) );
        page->save( mCollection );
      }

      CollectionModifyJob *job = new CollectionModifyJob( mCollection, q );
      connect( job, SIGNAL(result(KJob*)), q, SLOT(saveResult(KJob*)) );
    }

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

    void setCurrentPage( const QString &name )
    {
      for ( int i = 0; i < mTabWidget->count(); ++i ) {
        QWidget *w = mTabWidget->widget( i );
        if ( w->objectName() == name ) {
          mTabWidget->setCurrentIndex( i );
          break;
        }
      }
    }

    CollectionPropertiesDialog *q;
    Collection mCollection;
    QStringList mPageNames;
    KTabWidget* mTabWidget;
};

typedef QList<CollectionPropertiesPageFactory*> CollectionPropertiesPageFactoryList;

K_GLOBAL_STATIC( CollectionPropertiesPageFactoryList, s_pages )

static bool s_defaultPage = true;

CollectionPropertiesDialog::Private::Private( CollectionPropertiesDialog *qq, const Akonadi::Collection &collection, const QStringList &pageNames )
  : q( qq ),
    mCollection( collection ),
    mPageNames( pageNames ),
    mTabWidget( 0 )
{
  if ( s_defaultPage ) {
    registerBuiltinPages();
  }
}

void CollectionPropertiesDialog::Private::registerBuiltinPages()
{
  static bool registered = false;

  if ( registered ) {
    return;
  }

  s_pages->append( new CollectionGeneralPropertiesPageFactory() );
  s_pages->append( new CachePolicyPageFactory() );

  registered = true;
}

void CollectionPropertiesDialog::Private::init()
{
  QBoxLayout *layout = new QHBoxLayout( q->mainWidget() );
  layout->setMargin( 0 );
  mTabWidget = new KTabWidget( q->mainWidget() );
  layout->addWidget( mTabWidget );

  if ( mPageNames.isEmpty() ) { // default loading
    foreach ( CollectionPropertiesPageFactory *factory, *s_pages ) {
      CollectionPropertiesPage *page = factory->createWidget( mTabWidget );
      if ( page->canHandle( mCollection ) ) {
        mTabWidget->addTab( page, page->pageTitle() );
        page->load( mCollection );
      } else {
        delete page;
      }
    }
  } else { // custom loading
    QHash<QString, CollectionPropertiesPage*> pages;

    foreach ( CollectionPropertiesPageFactory *factory, *s_pages ) {
      CollectionPropertiesPage *page = factory->createWidget( mTabWidget );
      const QString pageName = page->objectName();

      if ( page->canHandle( mCollection ) && mPageNames.contains( pageName ) && !pages.contains( pageName ) ) {
        pages.insert( page->objectName(), page );
      } else {
        delete page;
      }
    }

    foreach ( const QString &pageName, mPageNames ) {
      CollectionPropertiesPage *page = pages.value( pageName );
      if ( page ) {
        mTabWidget->addTab( page, page->pageTitle() );
        page->load( mCollection );
      }
    }
  }

  q->connect( q, SIGNAL(okClicked()), SLOT(save()) );
  q->connect( q, SIGNAL(cancelClicked()), SLOT(deleteLater()) );

  KConfigGroup group( KGlobal::config(), "CollectionPropertiesDialog" );
  const QSize size = group.readEntry( "Size", QSize() );
  if ( size.isValid() ) {
    q->resize( size );
  } else {
    q->resize( q->sizeHint().width(), q->sizeHint().height() );
  }

}

CollectionPropertiesDialog::CollectionPropertiesDialog( const Collection &collection, QWidget *parent )
  : KDialog( parent ),
    d( new Private( this, collection, QStringList() ) )
{
  d->init();
}

CollectionPropertiesDialog::CollectionPropertiesDialog( const Collection &collection, const QStringList &pages, QWidget *parent )
  : KDialog( parent ),
    d( new Private( this, collection, pages ) )
{
  d->init();
}

CollectionPropertiesDialog::~CollectionPropertiesDialog()
{
  KConfigGroup group( KGlobal::config(), "CollectionPropertiesDialog" );
  group.writeEntry( "Size", size() );
  delete d;
}

void CollectionPropertiesDialog::registerPage( CollectionPropertiesPageFactory *factory )
{
  if ( s_pages->isEmpty() && s_defaultPage ) {
    Private::registerBuiltinPages();
  }
  s_pages->append( factory );
}

void CollectionPropertiesDialog::useDefaultPage( bool defaultPage )
{
  s_defaultPage = defaultPage;
}

QString CollectionPropertiesDialog::defaultPageObjectName( DefaultPage page )
{
  switch ( page ) {
    case GeneralPage:
      return QLatin1String( "Akonadi::CollectionGeneralPropertiesPage" );
    case CachePage:
      return QLatin1String( "Akonadi::CachePolicyPage" );
  }

  return QString();
}

void CollectionPropertiesDialog::setCurrentPage( const QString &name )
{
  d->setCurrentPage( name );
}

#include "moc_collectionpropertiesdialog.cpp"
