/*
    accountconfig.cpp  -  Kopete account config page

    Copyright (c) 2003-2004 by Olivier Goffart        <ogoffart @ kde.org>
    Copyright (c) 2003      by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2003-2004 by the Kopete developers  <kopete-devel@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.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "kopeteaccountconfig.h"

#include <tqcheckbox.h>
#include <tqlayout.h>
#include <tqguardedptr.h>

#include <kcolorbutton.h>
#include <kpushbutton.h>
#include <kdebug.h>
#include <kdialogbase.h>
#include <kgenericfactory.h>
#include <kiconloader.h>
#include <tdelistview.h>
#include <tdelocale.h>
#include <tdemessagebox.h>

#include "addaccountwizard.h"
#include "editaccountwidget.h"
#include "kopeteaccountconfigbase.h"
#include "kopeteaccountmanager.h"
#include "kopeteprotocol.h"
#include "kopeteaccount.h"

class KopeteAccountLVI : public TDEListViewItem
{
	public:
		KopeteAccountLVI( Kopete::Account *a, TDEListView *p ) : TDEListViewItem( p ){  m_account = a; }
		Kopete::Account *account() { return m_account; }

	private:
		//need to be guarded because some accounts may be linked (that's the case of jabber transports)
		TQGuardedPtr<Kopete::Account> m_account;
};

typedef KGenericFactory<KopeteAccountConfig, TQWidget> KopeteAccountConfigFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_kopete_accountconfig, KopeteAccountConfigFactory( "kcm_kopete_accountconfig" ) )

KopeteAccountConfig::KopeteAccountConfig( TQWidget *parent, const char * /* name */, const TQStringList &args )
: TDECModule( KopeteAccountConfigFactory::instance(), parent, args )
{

	( new TQVBoxLayout( this ) )->setAutoAdd( true );
	m_view = new KopeteAccountConfigBase( this, "KopeteAccountConfig::m_view" );

	m_view->mButtonUp->setIconSet( SmallIconSet( "go-up" ) );
	m_view->mButtonDown->setIconSet( SmallIconSet( "go-down" ) );

	connect( m_view->mButtonNew,    TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAddAccount() ) );
	connect( m_view->mButtonEdit,   TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotEditAccount() ) );
	connect( m_view->mButtonRemove, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotRemoveAccount() ) );
	connect( m_view->mButtonUp,     TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAccountUp() ) );
	connect( m_view->mButtonDown,   TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotAccountDown() ) );
	connect( m_view->mAccountList,  TQ_SIGNAL( selectionChanged() ), this, TQ_SLOT( slotItemSelected() ) );
	connect( m_view->mAccountList,  TQ_SIGNAL( doubleClicked( TQListViewItem * ) ), this, TQ_SLOT( slotEditAccount() ) );
	connect( m_view->mUseColor,     TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotColorChanged() ) );
	connect( m_view->mColorButton,  TQ_SIGNAL( changed( const TQColor & ) ), this, TQ_SLOT( slotColorChanged() ) );

	m_view->mAccountList->setSorting(-1);

	setButtons( Help );
	load();
}

void KopeteAccountConfig::save()
{
	uint priority = m_view->mAccountList->childCount();

	KopeteAccountLVI *i = static_cast<KopeteAccountLVI*>( m_view->mAccountList->firstChild() );
	while( i )
	{
		if(!i->account())
			continue;
		i->account()->setPriority( priority-- );
		i = static_cast<KopeteAccountLVI*>( i->nextSibling() );
	}

	TQMap<Kopete::Account *, TQColor>::Iterator it;
	for(it=m_newColors.begin() ; it != m_newColors.end() ; ++it)
		it.key()->setColor(it.data());
	m_newColors.clear();

	Kopete::AccountManager::self()->save();

	load(); //refresh the colred accounts (in case of apply)
}

void KopeteAccountConfig::load()
{
	KopeteAccountLVI *lvi = 0L;

	m_view->mAccountList->clear();

	TQPtrList<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts();
	for ( Kopete::Account *i = accounts.first() ; i; i = accounts.next() )
	{
		// Insert the item after the previous one
		lvi = new KopeteAccountLVI( i, m_view->mAccountList );
		lvi->setText( 0, i->protocol()->displayName() );
		lvi->setPixmap( 0, i->accountIcon() );
		lvi->setText( 1, i->accountLabel() );
	}

	m_newColors.clear();
	slotItemSelected();
}

void KopeteAccountConfig::slotItemSelected()
{
	m_protected=true;
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );

	m_view->mButtonEdit->setEnabled( itemSelected );
	m_view->mButtonRemove->setEnabled( itemSelected );

	if ( itemSelected &&  itemSelected->account() )
	{
		m_view->mButtonUp->setEnabled( itemSelected->itemAbove() );
		m_view->mButtonDown->setEnabled( itemSelected->itemBelow() );

		Kopete::Account *account = itemSelected->account();
		TQColor color= m_newColors.contains(account) ? m_newColors[account] :  account->color();
		m_view->mUseColor->setEnabled( true );
		m_view->mUseColor->setChecked( color.isValid() );
		m_view->mColorButton->setColor( color );
		m_view->mColorButton->setEnabled( m_view->mUseColor->isChecked() );

	}
	else
	{
		m_view->mButtonUp->setEnabled( false );
		m_view->mButtonDown->setEnabled( false);
		m_view->mUseColor->setEnabled( false );
		m_view->mColorButton->setEnabled( false );
	}
	m_protected=false;
}

void KopeteAccountConfig::slotAccountUp()
{
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !itemSelected )
		return;

	if ( itemSelected->itemAbove() )
		itemSelected->itemAbove()->moveItem( itemSelected );

	slotItemSelected();
	emit changed( true );
}

void KopeteAccountConfig::slotAccountDown()
{
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !itemSelected )
		return;

	itemSelected->moveItem( itemSelected->itemBelow() );

	slotItemSelected();
	emit changed( true );
}

void KopeteAccountConfig::slotAddAccount()
{
	AddAccountWizard *m_addwizard = new AddAccountWizard( this, "addAccountWizard", true );
	connect( m_addwizard, TQ_SIGNAL( destroyed( TQObject * ) ), this, TQ_SLOT( slotAddWizardDone() ) );
	m_addwizard->show();
}

void KopeteAccountConfig::slotEditAccount()
{
	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi || !lvi->account() )
		return;

	Kopete::Account *ident = lvi->account();
	Kopete::Protocol *proto = ident->protocol();

	KDialogBase *editDialog = new KDialogBase( this, "KopeteAccountConfig::editDialog", true,
		i18n( "Edit Account" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true );

	KopeteEditAccountWidget *m_accountWidget = proto->createEditAccountWidget( ident, editDialog );
	if ( !m_accountWidget )
		return;

	// FIXME: Why the #### is EditAccountWidget not a TQWidget?!? This sideways casting
	//        is braindead and error-prone. Looking at MSN the only reason I can see is
	//        because it allows direct subclassing of designer widgets. But what is
	//        wrong with embedding the designer widget in an empty TQWidget instead?
	//        Also, if this REALLY has to be a pure class and not a widget, then the
	//        class should at least be renamed to EditAccountIface instead - Martijn
	TQWidget *w = dynamic_cast<TQWidget *>( m_accountWidget );
	if ( !w )
		return;

	editDialog->setMainWidget( w );
	if ( editDialog->exec() == TQDialog::Accepted )
	{
		if( m_accountWidget->validateData() )
			m_accountWidget->apply();
	}

	// FIXME: Why deleteLater? It shouldn't be in use anymore at this point - Martijn
	editDialog->deleteLater();
	load();
	Kopete::AccountManager::self()->save();
}

void KopeteAccountConfig::slotRemoveAccount()
{
	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi || !lvi->account() )
		return;

	Kopete::Account *i = lvi->account();
	if ( KMessageBox::warningContinueCancel( this, i18n( "Are you sure you want to remove the account \"%1\"?" ).arg( i->accountLabel() ),
		i18n( "Remove Account" ), KGuiItem(i18n( "Remove Account" ), "edit-delete"),
		 "askRemoveAccount", KMessageBox::Notify | KMessageBox::Dangerous ) == KMessageBox::Continue )
	{
		Kopete::AccountManager::self()->removeAccount( i );
		delete lvi;
	}
}

void KopeteAccountConfig::slotAddWizardDone()
{
	save();
	load();
}

void KopeteAccountConfig::slotColorChanged()
{
	if(m_protected)  //this slot is called because we changed the button
		return;      // color because another account has been selected

	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi || !lvi->account() )
		return;
	Kopete::Account *account = lvi->account();

	if(!account->color().isValid() && !m_view->mUseColor->isChecked() )
	{  //we don't use color for that account and nothing changed.
		m_newColors.remove(account);
		return;
	}
	else if(!m_view->mUseColor->isChecked())
	{  //the user disabled account coloring, but it was activated before
		m_newColors[account]=TQColor();
		emit changed(true);
		return;
	}
	else if(account->color() == m_view->mColorButton->color() )
	{   //The color has not changed.
		m_newColors.remove(account);
		return;
	}
	else
	{
		m_newColors[account]=m_view->mColorButton->color();
		emit changed(true);
	}
}

#include "kopeteaccountconfig.moc"
