/*
 *
 * Copyright (C) 2002 George Staikos <staikos@kde.org>
 *               2003 Dirk Ziegelmeier <dziegel@gmx.de>
 *
 * 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 Steet, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */


#ifndef _PLUGINFACTORY_H
#define _PLUGINFACTORY_H

#include <qstring.h>
#include <qwidget.h>
#include <qmap.h>
#include <qlist.h>
#include <kservice.h>

class KdetvPluginBase;
class KdetvSourcePlugin;
class KdetvMixerPlugin;
class KdetvOSDPlugin;
class KdetvMiscPlugin;
class KdetvChannelPlugin;
class KdetvVbiPlugin;
class KdetvFilterPlugin;
class PluginFactory;
class KActionCollection;
class KXMLGUIFactory;

/**
 * Internal description of a plugin
 */
class PluginDesc
{
public:
    typedef enum { UNKNOWN, VIDEO, CHANNEL, MIXER, OSD, MISC, IMAGEFILTER, POSTPROCESS, VBI } PluginType;
    PluginDesc(PluginFactory* factory);
    virtual ~PluginDesc();

    int id;
    QString       factory;
    QString       name;
    QString       author;
    QString       comment;
    QString       icon;
    QString       lib;
    KService::Ptr service;
    PluginType    type;
    bool          configurable;
    bool          enabled;

    friend int operator< (const PluginDesc& l, const PluginDesc& r);
    friend int operator> (const PluginDesc& l, const PluginDesc& r);
    friend int operator==(const PluginDesc& l, const PluginDesc& r);
    friend int operator!=(const PluginDesc& l, const PluginDesc& r);

    PluginFactory* getFactory() { return _factory; };

 private:
    friend class PluginFactory;
    int _refCount;
    KdetvPluginBase*  _instance;
    PluginFactory* _factory;
};


class KConfig;
class Kdetv;

/**
 * The factory where all the plugins come from.
 * Has lists of plugin descriptors.
 */
class PluginFactory
{
public:
    QList<PluginDesc*>& videoPlugins()       { return _videoPlugins;       };
    QList<PluginDesc*>& channelPlugins()     { return _channelPlugins;     };
    QList<PluginDesc*>& mixerPlugins()       { return _mixerPlugins;       };
    QList<PluginDesc*>& miscPlugins()        { return _miscPlugins;        };
    QList<PluginDesc*>& osdPlugins()         { return _osdPlugins;         };
    QList<PluginDesc*>& vbiPlugins()         { return _vbiPlugins;         };
    QList<PluginDesc*>& filterPlugins()      { return _filterPlugins;      };
    QList<PluginDesc*>& postProcessPlugins() { return _postProcessPlugins; };

    /**
     * Returns pointer to plugin instance. Instance is refcounted.
     * Don't destroy plugin manually, use putPlugin().
     */
    KdetvMixerPlugin*   getMixerPlugin(PluginDesc* plugin);
    KdetvChannelPlugin* getChannelPlugin(PluginDesc* plugin);
    KdetvOSDPlugin*     getOSDPlugin(PluginDesc* plugin, QWidget* o);
    KdetvMiscPlugin*    getMiscPlugin(PluginDesc* plugin, QWidget* o);
    KdetvSourcePlugin*  getSourcePlugin(PluginDesc* plugin, QWidget* o);
    KdetvVbiPlugin*     getVbiPlugin(PluginDesc* plugin, QObject* parent);
    KdetvFilterPlugin*  getFilterPlugin(PluginDesc* plugin);
    KdetvFilterPlugin*  getPostProcessPlugin(PluginDesc* plugin);

    /**
     * To be called if the plugin is no longer used.
     * Destroys plugin if there are no more references.
     * Usually called from aPluginInstance->destroy().
     */
    void putPlugin(PluginDesc* plugin);

protected:
    friend class Kdetv;
    PluginFactory(Kdetv *ktv);
    virtual ~PluginFactory();

    virtual void scanForPlugins(KConfig* cfg);
    void doScan(KConfigGroup* cfg, KService::List& plugs, QList<PluginDesc*>& list, PluginDesc::PluginType type);

    /**
     * Sets GUI factory. Calls removeGUIElements() on all instanciated plugins if there
     * was already a factory set. Calls installGUIElements() on all instanciated plugins.
     */
    void setGUIFactory(KXMLGUIFactory*, KActionCollection*);

    KdetvPluginBase* getPluginRefCounted(PluginDesc* plugin, bool qWidgetArg, QObject* o);
    KdetvPluginBase* doGetPlugin(PluginDesc* plugin, bool qWidgetArg, QObject* o);

private:
    static int _upid;

    QList<PluginDesc*> _videoPlugins;
    QList<PluginDesc*> _mixerPlugins;
    QList<PluginDesc*> _osdPlugins;
    QList<PluginDesc*> _channelPlugins;
    QList<PluginDesc*> _miscPlugins;
    QList<PluginDesc*> _vbiPlugins;
    QList<PluginDesc*> _filterPlugins;
    QList<PluginDesc*> _postProcessPlugins;
    QList<PluginDesc*> _allPlugins;

    Kdetv *_ktv;

    KActionCollection* _actionCollection;
    KXMLGUIFactory*    _factory;
};

#endif
