
#include <assert.h>

#include <kglobal.h>
#include <klocale.h>

#include <qbttngrp.h>
#include <qradiobt.h>
#include <qpushbt.h>
//#include <typolayout.h>
#include <qlistbox.h>
#include <qlist.h>
#include <qlayout.h>

#include "maildrop.h"
#include "dropman.h"
#include "optdlg.h"
#include "typedlg.h"


KornOptDlg::KornOptDlg( KDropManager *man, QWidget *parent )
	: QTabDialog( parent ),
	_dropDlgList( 0 ),
	_monitorList( 0 )
{
	assert( man );
	_manager = man;

	connect( _manager, SIGNAL(monitorCreated()), this,
		SLOT(updateList()));

	connect( _manager, SIGNAL(monitorDeleted()), this,
		SLOT(updateList()));

	connect( _manager, SIGNAL(configChanged()), this,
		SLOT(updateList()));

	setCaption( i18n( "Korn: Options" ) );

	// Options

	QWidget *page = new QWidget( this );

	QBoxLayout *_layout = new QVBoxLayout( page, 10 );
	_layout->addSpacing(10);

	QButtonGroup *aGroup = new QButtonGroup( i18n( "Layout" ), page );
	_layout->addWidget( aGroup);

	QBoxLayout *slay = new QVBoxLayout(aGroup, 10);
	slay->addSpacing(10);

	_horiz	= new QRadioButton( i18n( "Horizontal" ), aGroup );
	slay->addWidget( _horiz );

	_vert	= new QRadioButton( i18n( "Vertical" ),	  aGroup );
	slay->addWidget( _vert );

	_dock	= new QRadioButton( i18n( "Docked" ),     aGroup );
	slay->addWidget( _dock );

	addTab( page, i18n( "&Options" ) );



	// Boxes
	page = new QWidget( this );

	_layout = new QHBoxLayout( page, 10 );
	_layout->addSpacing(10);

	// initialize monitor list
	// list is filled at the end so that all signals
	// are connected properly.

	_listBox = new QListBox( page );
	_layout->addWidget( _listBox );

	connect( _listBox, SIGNAL(selected(int)), 
			this, SLOT(modifyBox()) );

	connect( _listBox, SIGNAL(highlighted(int)),
		this, SLOT(enableButtons()));

	// up/down buttons


	// initialize buttons

	slay = new QVBoxLayout( 10 );
	_layout->addLayout( slay );
	slay->addSpacing(10);

	QPushButton *b = new QPushButton( i18n( "&Modify" ), page );
	slay->addWidget( b );

	connect( this, SIGNAL(listUpdated(bool)), b,
		SLOT(setEnabled(bool)) );

	connect( b, SIGNAL(clicked()), this, SLOT(modifyBox()) );

	b = new QPushButton( i18n( "&New" ), page );
	slay->addWidget( b );

	connect( b, SIGNAL(clicked()), this, SLOT(newBox()) );

	b = new QPushButton( i18n( "&Delete" ), page );
	slay->addWidget( b );

	connect( b, SIGNAL(clicked()), this, SLOT(deleteBox()) );

	connect( this, SIGNAL(listUpdated(bool)), b,
		SLOT(setEnabled(bool)) );

	b = new QPushButton( i18n( "&Clone" ), page );
	slay->addWidget( b );

	connect( this, SIGNAL(listUpdated(bool)), b,
		SLOT(setEnabled(bool)) );

	connect( b, SIGNAL(clicked()), this, SLOT(cloneBox()) );

	b = new QPushButton( i18n( "&Setup ..." ), page );
	slay->addWidget( b );

	connect( b, SIGNAL(clicked()), this, SLOT(modifyBox()) );

	connect( this, SIGNAL(listUpdated(bool)), b,
		SLOT(setEnabled(bool)) );

	addTab( page, i18n( "&Boxes" ) );

	setOkButton( i18n( "&OK" ) );
	setCancelButton( i18n( "&Cancel" ) );

	connect( this, SIGNAL(applyButtonPressed()), this, SLOT(apply()) );
	connect( this, SIGNAL(cancelButtonPressed()), this, SLOT(cancel()) );

	fillListBox();
}

KornOptDlg::~KornOptDlg()
{
	delete _dropDlgList;
	delete _monitorList;
}

void KornOptDlg::fillListBox()
{
	_listBox->clear();

	if( _monitorList == 0 ) {
		_monitorList = new QIntDict<KMailDrop>;
		_monitorList->setAutoDelete( false );
	}
	else {
		_monitorList->clear();
	}

	QListIterator<KMailDrop> iter = _manager->monitors();

	if( !iter.current() ) {
		// empty list
		emit listUpdated( false );
		return;
	}

	int index = 0;
	for( ; iter.current(); ++iter ) {
		if( iter.current()->caption() == 0 ) {
			warning( "maildrop of type %s has no caption",
				iter.current()->type() );
		}
		else {
			_listBox->insertItem( 
				iter.current()->caption(), index );
			_monitorList->insert( index, iter.current() );
			index++;
		}
	}

	// make sure one item is always selected
	if( _listBox->currentItem() < 0 ) {
		emit listUpdated( false );
	}
	else {
		emit listUpdated( true );
	}
}

void KornOptDlg::cancel()
{
	emit finished( 0 );
}

void KornOptDlg::apply()
{
	emit finished( 1 );
}

void KornOptDlg::setKornLayout( KornSettings::Layout layout )
{
	switch( layout ) {
		case KornSettings::Horizontal:	
			_horiz->setChecked( true );	
			break;
		case KornSettings::Vertical:	
			_vert->setChecked( true );	
			break;
		case KornSettings::Dock:	
			_dock->setChecked( true );	
			break;
		default:
			break;
	}
}

KornSettings::Layout KornOptDlg::kornLayout() const
{
	// there ought to be a nicer
	// way than this..

	if( _horiz->isChecked() ) {
		return KornSettings::Horizontal;
	}
	else if( _vert->isChecked() ) {
		return KornSettings::Vertical;
	}
	else if( _dock->isChecked() ) {
		return KornSettings::Dock;
	}

	warning( "kornLayout: no layout option is selected." );
			
	// shouldn't get here
	return KornSettings::Horizontal;
}


void KornOptDlg::newBox()
{
	TypeDialog *dlg = new TypeDialog( _manager->types(), 
			0, i18n("Type"), true );
		
	bool selected = dlg->exec();

	if( selected == true ) {
		// type selected

		// new monitor

		KMailDrop *drop = _manager->newMonitor( dlg->type() );
		drop->setCaption( i18n( "New Monitor" ) );

		// new config dialog

		KDropCfgDialog *dropcfg = dropDialog( drop, false );

		dropcfg->show();
	}

	delete dlg;
}

void KornOptDlg::deleteBox()
{
	KMailDrop *monitor = getMonitor();

	if( monitor == 0 ) {
		return;
	}

	// delete associated config dialog

	if( _dropDlgList ) {
		_dropDlgList->remove( monitor );
	}

	_manager->deleteMonitor( monitor );
}

void KornOptDlg::cloneBox()
{
	KMailDrop *monitor = getMonitor();

	if( monitor == 0 ) {
		warning( "cloneBox: getMonitor() returned null." );
		return;
	}

	// clone monitor

	monitor = _manager->cloneMonitor( monitor );

	if( monitor == 0 ) {
		warning( "cloneBox: cloneMonitor() returned null." );
		return;
	}
	// display monitor

	KDropCfgDialog *dropcfg = dropDialog( monitor, false );

	dropcfg->show();
}

KMailDrop *KornOptDlg::getMonitor() const
{
	// get monitor

	KMailDrop *monitor = _monitorList->find( _listBox->currentItem() );

	if( monitor == 0 ) {
		warning( "KornOptDlg::modifyBox: no monitor found for"
				" listbox item '%d'.", 
				_listBox->currentItem() );
	}

	return monitor;
}

void KornOptDlg::modifyBox()
{

	// display config dialog.

	KMailDrop *monitor = getMonitor();

	if( monitor == 0 ) {
		return;
	}

	KDropCfgDialog *dlg = dropDialog( monitor );

	dlg->show();

	return;
}

QPtrDict<KDropCfgDialog> *KornOptDlg::dlgList()
{
	if( _dropDlgList == 0 ) {
		// new list
		_dropDlgList = new QPtrDict<KDropCfgDialog>;
		assert( _dropDlgList != 0 );

		_dropDlgList->setAutoDelete( true );
	}

	return _dropDlgList;
}

void KornOptDlg::dlgClosed( KDropCfgDialog *dlg )
{
	assert( dlg );
	assert( _dropDlgList != 0 );

	QPtrDictIterator<KDropCfgDialog> iter(  *_dropDlgList );

	while( iter.current() ) {
		if( iter.current() == dlg ) {
			// found! remove it
			_dropDlgList->take( iter.currentKey() );
			return;
		}
		else {
			// nope, this is not it.
			++iter;
		}
	}
	warning( "dlgClosed: Disassociated dialog %s not "
		"found in dialog list.",
		dlg->caption().ascii() );
}

KDropCfgDialog *KornOptDlg::dropDialog( KMailDrop *drop, 
	bool checkExists )
{
	assert( drop );
	KDropCfgDialog *dlg;

	if( checkExists && _dropDlgList ) {
		// exists check
		dlg  = _dropDlgList->find( drop );	

		if( dlg != 0 ) {
			return dlg;
		}
	}

	dlg =  new KDropCfgDialog( drop->caption() );
	assert( dlg != 0 );

	drop->addConfigPage( dlg );
	dlgList()->insert( drop, dlg );

	connect( dlg, SIGNAL(disassociate(KDropCfgDialog*)),
			this, SLOT(dlgClosed(KDropCfgDialog*)) );

	return dlg;
}

void KornOptDlg::updateList()
{
	fillListBox();
}

void KornOptDlg::enableButtons()
{
	emit listUpdated(true);
}
