/***************************************************************************
                          pluginwidgetimpl.cpp  -  description
                             -------------------
    begin                : Sat Jun 8 2002
    copyright            : (C) 2002 by Kevin Hessels <khessels@shaw.ca
                           (C) 2002 George Staikos <staikos@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 <qtabwidget.h>
#include <qlayout.h>
#include <qsplitter.h>

#include <kdialog.h>
#include <klistview.h>
#include <kpushbutton.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kconfig.h>

#include "pluginfactory.h"
#include "pluginwidgetimpl.h"
#include "audiomanager.h"
#include "osdmanager.h"
#include "miscmanager.h"

#include "qvmixerplugin.h"
#include "qvosdplugin.h"
#include "qvsrcplugin.h"
#include "qvmiscplugin.h"

#define PLUGIN_RTTI  49859

class PluginListItem : public QCheckListItem
{
	public:
		PluginListItem(KListView*, PluginDesc*, bool);
		virtual ~PluginListItem();
		
		virtual int rtti() const;

        PluginDesc *pd;
};


PluginListItem::PluginListItem(KListView *parent, PluginDesc *d, bool exclusive)
               :QCheckListItem(parent, d->name, exclusive ? QCheckListItem::RadioButton : QCheckListItem::CheckBox)
{
	setText(1, d->author);
	setText(2, d->comment);
	pd = d;
	setOn(pd->enabled);
}

PluginListItem::~PluginListItem()
{
    return;
}

int PluginListItem::rtti() const
{
	return PLUGIN_RTTI;
}


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


PluginWidgetImpl::PluginWidgetImpl(QWidget *parent, QtVision *qtv) 
: PluginWidget(parent), _qtv(qtv)
{
    setupVideoTab();
    setupMixerTab();
    setupChannelFmtTab();
    setupMiscTab();

    connect(_tabs, SIGNAL(currentChanged(QWidget *)), this, SLOT(slotPageChanged(QWidget *)));
    connect(videoListView, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotListItemClicked(QListViewItem *)));
    connect(mixerListView, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotListItemClicked(QListViewItem *)));
    connect(channelListView, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotListItemClicked(QListViewItem *)));
    connect(miscListView, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotListItemClicked(QListViewItem *)));
    connect(_configure, SIGNAL(clicked()), this, SLOT(slotConfigurePlugin()));
    return;
} // PluginWidgetImpl constructor


PluginWidgetImpl::~PluginWidgetImpl()
{
    return;
} // PluginWidgetImpl destructor


void PluginWidgetImpl::applyPlugins(KConfig *cfg)
{
    for (int i = 0; i < _tabs->count(); i++) {
        switch (i) {
            case page_video:
		cfg->setGroup("Video Plugins");
                applyPlugins(videoListView, cfg);
                break;
            case page_mixer:
		cfg->setGroup("Mixer Plugins");
                applyPlugins(mixerListView, cfg);
		_qtv->audioManager()->rescanPlugins();
                break;
            case page_channelfmt:
		cfg->setGroup("Channel Plugins");
                applyPlugins(channelListView, cfg);
                break;
            case page_misc:
		cfg->setGroup("Misc Plugins");
                applyPlugins(miscListView, cfg);
		_qtv->osdManager()->rescanPlugins();
		_qtv->miscManager()->rescanPlugins();
                break;
            default:
                break;
        } // switch
    } // for
    return;
} // applyPlugins


/***************************************************************************
*
* Private
*
***************************************************************************/


void PluginWidgetImpl::setupVideoTab()
{
    for (PluginDesc *plug = _qtv->pluginFactory()->videoPlugins().first(); plug;
                          plug = _qtv->pluginFactory()->videoPlugins().next())
    {
        new PluginListItem(videoListView, plug, false);
    } // for
    return;
} // setupVideoTab


void PluginWidgetImpl::setupMixerTab()
{
    for (PluginDesc *plug = _qtv->pluginFactory()->mixerPlugins().first(); plug;
                          plug = _qtv->pluginFactory()->mixerPlugins().next())
    {
        new PluginListItem(mixerListView, plug, false);
    } // for
    return;
} // setupMixerTab


void PluginWidgetImpl::setupChannelFmtTab()
{
    for (PluginDesc *plug = _qtv->pluginFactory()->channelPlugins().first();
                  plug; plug = _qtv->pluginFactory()->channelPlugins().next())
    {
        new PluginListItem(channelListView, plug, false);
    } // for
    return;
} // setupChannelFmtTab


void PluginWidgetImpl::setupMiscTab()
{
    for (PluginDesc *plug = _qtv->pluginFactory()->osdPlugins().first(); plug;
                          plug = _qtv->pluginFactory()->osdPlugins().next())
    {
        new PluginListItem(miscListView, plug, false);
    } // for
    for (PluginDesc *plug = _qtv->pluginFactory()->miscPlugins().first(); plug;
                          plug = _qtv->pluginFactory()->miscPlugins().next())
    {
        new PluginListItem(miscListView, plug, false);
    } // for
    return;
} // setupMiscTab


void PluginWidgetImpl::applyPlugins(KListView *listview, KConfig *cfg)
{
    QListViewItemIterator it(listview);
    for ( ; it.current(); ++it) {
        PluginListItem *item = static_cast<PluginListItem *>(it.current());
        item->pd->enabled = item->isOn();
        cfg->writeEntry(item->pd->name+"-"+item->pd->author, item->pd->enabled);
         //kdDebug() << "applyPlugins: " << item->pd->comment << " is on? "
         //<< (item->isOn()?"YES":"NO") << endl;
        // FIXME: Do something with the settings, load, unload as necessary.
    } // for
    return;
} // applyPlugins


/***************************************************************************
*
* Private slots
*
***************************************************************************/


void PluginWidgetImpl::slotConfigurePlugin()
{
    KDialog *kdb = new KDialog(this, "plugin config panel");
    QString name;
    QVPluginBase *p = 0;
    bool deletePlugin = false;

    QGridLayout *grid = new QGridLayout(kdb, 10, 10);
    KPushButton *ok_b = new KPushButton(i18n("&Ok"), kdb);
    KPushButton *cancel_b = new KPushButton(i18n("&Cancel"), kdb);
    QSplitter *sp = new QSplitter(QSplitter::Horizontal, kdb);
    QWidget *mw = 0;
    grid->addMultiCellWidget(sp, 8, 8, 0, 9);
    grid->addMultiCellWidget(ok_b, 9, 9, 7, 7);
    grid->addMultiCellWidget(cancel_b, 9, 9, 9, 9);
    connect(ok_b, SIGNAL(clicked()), kdb, SLOT(accept()));
    connect(cancel_b, SIGNAL(clicked()), kdb, SLOT(reject()));

    switch (_tabs->currentPageIndex()) {
        case page_video:
            {
            QListViewItem *pli = videoListView->selectedItem();

            if (!pli || !static_cast<PluginListItem*>(pli)->pd->configurable)
                break;

            printf("have device in qtvision? %s\n", _qtv->device()?"true":"false");

            if (_qtv->device()) {
                printf("Listview item is %s\n", (*static_cast<PluginListItem*>(pli)->pd).name.latin1());
                printf("QTVision item is %s\n", _qtv->device()->pluginDescription().name.latin1());
            }

            if (_qtv->device() &&
                *static_cast<PluginListItem*>(pli)->pd == 
                               _qtv->device()->pluginDescription())
                p = _qtv->device();

            if (!p)
            for (PluginDesc *plug = _qtv->pluginFactory()->videoPlugins().first(); plug; plug = _qtv->pluginFactory()->videoPlugins().next()) {
                if (*plug == *static_cast<PluginListItem*>(pli)->pd) {
                    p = _qtv->pluginFactory()->getVideoPlugin(plug, _qtv->screen());
                    deletePlugin = true;
                    break;
                }
            }

            if (p) {
                mw = p->configWidget(kdb, "Video Configuration Widget");
            }
            }
            break;
        case page_mixer:
            {
            QListViewItem *pli = mixerListView->selectedItem();

            if (!pli || !static_cast<PluginListItem*>(pli)->pd->configurable)
                break;

            QVMixerPlugin *mp = _qtv->audioManager()->plugin();

            if (mp && mp->pluginDescription() == *static_cast<PluginListItem*>(pli)->pd)
                p = mp;

            if (!p)
            for (PluginDesc *plug = _qtv->pluginFactory()->mixerPlugins().first(); plug; plug = _qtv->pluginFactory()->mixerPlugins().next()) {
                if (*plug == *static_cast<PluginListItem*>(pli)->pd) {
                    p = _qtv->pluginFactory()->getMixerPlugin(plug);
                    deletePlugin = true;
                    break;
                }
            }

            if (p) {
                mw = p->configWidget(kdb, "Mixer Configuration Widget");
            }
            }
            break;
        case page_channelfmt:
            break;
        case page_misc:
            {
            QListViewItem *pli = miscListView->selectedItem();

            if (!pli || !static_cast<PluginListItem*>(pli)->pd->configurable)
                break;

            // First check OSD plugins
            QVOSDPlugin *mp = _qtv->osdManager()->plugin();

            if (mp && mp->pluginDescription() == *static_cast<PluginListItem*>(pli)->pd)
                p = mp;

            // Try misc plugins
            if (!p) {
                QPtrList<QVMiscPlugin> plugs = _qtv->miscManager()->plugins();
                for (QVMiscPlugin *pi = plugs.first(); pi; pi = plugs.next()) {
                    if (pi->pluginDescription() == 
                                      *static_cast<PluginListItem*>(pli)->pd) {
                        p = pi;
                        break;
                    }
                }
            }

            // Search OSD
            if (!p)
            for (PluginDesc *plug = _qtv->pluginFactory()->osdPlugins().first();
		 plug; plug = _qtv->pluginFactory()->osdPlugins().next()) {
                if (*plug == *static_cast<PluginListItem*>(pli)->pd) {
                    p = _qtv->pluginFactory()->getOSDPlugin(plug, 0);
                    deletePlugin = true;
                    break;
                }
            }

            // Search Misc
            if (!p) {
                for (PluginDesc *plug = _qtv->pluginFactory()->miscPlugins().first(); plug; plug = _qtv->pluginFactory()->miscPlugins().next()) {
                    if (*plug == *static_cast<PluginListItem*>(pli)->pd) {
                        p = _qtv->pluginFactory()->getMiscPlugin(plug, 0);
                        deletePlugin = true;
                        break;
                    }
                }
            }

            if (p) {
                mw = p->configWidget(kdb, "Plugin Configuration Widget");
            }
            }
            break;
        default:
            break;
    } // switch

    if (mw) {
        grid->addMultiCellWidget(mw, 0, 7, 0, 9);
        kdb->setCaption(i18n("Configuration") + " - " + name);
        QSize ms(300,200);
        QSize nh = kdb->sizeHint().expandedTo(ms);
	grid->setResizeMode(QLayout::FreeResize);
        kdb->setMinimumSize(nh);
        kdb->resize(nh);

        int rc = kdb->exec();
        if (rc == QDialog::Accepted) {
		p->saveConfig();
	}
    } else {
        KMessageBox::sorry(this, i18n("This plugin is not configurable."), i18n("QtVision"));
    }

    delete kdb;

    if (deletePlugin)
        delete p;
} // slotConfigurePlugin


void PluginWidgetImpl::slotPageChanged(QWidget *)
{
    _configure->setEnabled(false);

    QListViewItem *i = 0;
    switch (_tabs->currentPageIndex()) {
        case page_video:
            i = videoListView->selectedItem();
            break;
        case page_mixer:
            i = mixerListView->selectedItem();
            break;
        case page_channelfmt:
            i = channelListView->selectedItem();
            break;
        case page_misc:
            i = miscListView->selectedItem();
            break;
        default:
            break;
    } // switch
    slotListItemClicked(i);
    return;
} // slotPageChanged


void PluginWidgetImpl::slotListItemClicked(QListViewItem *i)
{
    PluginListItem *item = static_cast<PluginListItem *>(i);

    if ( !item ) {
	_configure->setEnabled( false );
	return;
    }

    if ( item->rtti() != PLUGIN_RTTI )
        return;

    _configure->setEnabled(item->pd->configurable);

    return;
} // slotListItemClicked


