/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2004-06-04
 * Description : image plugins loader for image editor.
 * 
 * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
 * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
 *
 * 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, or (at your option)
 * any later version.
 * 
 * This program 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 General Public License for more details.
 * 
 * ============================================================ */

// KDE includes.

#include <ktrader.h>
#include <kparts/componentfactory.h>
#include <kapplication.h>
#include <klocale.h>
#include <kxmlguiclient.h>

// Local includes.

#include "ddebug.h"
#include "splashscreen.h"
#include "imagepluginloader.h"

namespace Digikam
{

// List of obsolete image plugins name. 

static const char* ObsoleteImagePluginsList[] =
{
     "digikamimageplugin_blowup",    // Merged with "Resize" tool since 0.9.2.  
     "digikamimageplugin_solarize",  // Renamed "ColorFx" since 0.9.2.  
     "digikamimageplugin_unsharp",   // Merged with "Sharpen" tool since 0.9.2.
     "digikamimageplugin_refocus",   // Merged with "Sharpen" tool since 0.9.2.
     "digikamimageplugin_despeckle", // Renamed "Noise Reduction" since 0.9.2.
     "-1"
};

class ImagePluginLoaderPrivate
{

public:

    typedef TQPair<TQString, ImagePlugin*> PluginType;
    typedef TQValueList< PluginType >     PluginList;

public:

    ImagePluginLoaderPrivate()
    {
        splash = 0;

        for (int i=0 ; TQString(ObsoleteImagePluginsList[i]) != TQString("-1") ; i++)
            obsoleteImagePluginsList << ObsoleteImagePluginsList[i];
    }
    
    TQStringList   obsoleteImagePluginsList;

    SplashScreen *splash;

    PluginList    pluginList;
};

ImagePluginLoader* ImagePluginLoader::m_instance=0;

ImagePluginLoader* ImagePluginLoader::instance()
{
    return m_instance;
}

ImagePluginLoader::ImagePluginLoader(TQObject *parent, SplashScreen *splash)
                 : TQObject(parent)
{
    m_instance = this;
    d = new ImagePluginLoaderPrivate;
    d->splash = splash;
 
    TQStringList imagePluginsList2Load;
    
    KTrader::OfferList offers = KTrader::self()->query("Digikam/ImagePlugin");
    KTrader::OfferList::ConstIterator iter;
    
    for (iter = offers.begin() ; iter != offers.end() ; ++iter) 
    {
        KService::Ptr service = *iter;
        if (!d->obsoleteImagePluginsList.contains(service->library()))
            imagePluginsList2Load.append(service->library());
    }
        
    loadPluginsFromList(imagePluginsList2Load);
}

ImagePluginLoader::~ImagePluginLoader()
{
    delete d;
    m_instance = 0;
}

void ImagePluginLoader::loadPluginsFromList(const TQStringList& list)
{
    if (d->splash)
        d->splash->message(i18n("Loading Image Plugins"));

    KTrader::OfferList offers = KTrader::self()->query("Digikam/ImagePlugin");
    KTrader::OfferList::ConstIterator iter;

    int cpt = 0;

    // Load plugin core at the first time.

    for(iter = offers.begin(); iter != offers.end(); ++iter)
    {
        KService::Ptr service = *iter;
        ImagePlugin *plugin;

        if (service->library() == "digikamimageplugin_core")
        {
            if (!pluginIsLoaded(service->name()) )
            {
                int error=-1;
                plugin = KParts::ComponentFactory::createInstanceFromService<ImagePlugin>(
                                 service, this, service->name().local8Bit(), 0, &error);

                if (plugin && (dynamic_cast<KXMLGUIClient*>(plugin) != 0))
                {
                    d->pluginList.append(ImagePluginLoaderPrivate::PluginType(service->name(), plugin));

                    DDebug() << "ImagePluginLoader: Loaded plugin " << service->name() << endl;

                    ++cpt;
                }
                else
                {
                    DWarning() << "ImagePluginLoader:: createInstanceFromLibrary returned 0 for "
                               << service->name()
                               << " (" << service->library() << ")"
                               << " with error code "
                               << error << endl;
                    if (error == KParts::ComponentFactory::ErrNoLibrary)
                        DWarning() << "KLibLoader says: "
                                   << KLibLoader::self()->lastErrorMessage() << endl;
                }
            }
            break;
        }
    }

    // Load all other image plugins after (make a coherant menu construction in Image Editor).

    for (iter = offers.begin(); iter != offers.end(); ++iter)
    {
        KService::Ptr service = *iter;
        ImagePlugin *plugin;

        if (!list.contains(service->library()) && service->library() != "digikamimageplugin_core")
        {
            if ((plugin = pluginIsLoaded(service->name())) != NULL)
                d->pluginList.remove(ImagePluginLoaderPrivate::PluginType(service->name(),plugin));
        }
        else 
        {
            if( pluginIsLoaded(service->name()) )
                continue;
            else
            {
                int error=-1;
                plugin = KParts::ComponentFactory::createInstanceFromService<ImagePlugin>(
                                 service, this, service->name().local8Bit(), 0);

                if (plugin && (dynamic_cast<KXMLGUIClient*>(plugin) != 0))
                {
                    d->pluginList.append(ImagePluginLoaderPrivate::PluginType(service->name(), plugin));

                    DDebug() << "ImagePluginLoader: Loaded plugin " << service->name() << endl;

                    ++cpt;
                }
                else
                {
                    DWarning() << "ImagePluginLoader:: createInstanceFromLibrary returned 0 for "
                               << service->name()
                               << " (" << service->library() << ")"
                               << " with error code "
                               << error << endl;
                    if (error == KParts::ComponentFactory::ErrNoLibrary)
                        DWarning() << "KLibLoader says: "
                                   << KLibLoader::self()->lastErrorMessage() << endl;
                }
            }
        }
    }

    d->splash = 0;       // Splashcreen is only lanched at the first time.
                         // If user change plugins list to use in setup, don't try to 
                         // use the old splashscreen instance.
}

ImagePlugin* ImagePluginLoader::pluginIsLoaded(const TQString& name)
{
    if ( d->pluginList.isEmpty() )
        return 0;

    for (ImagePluginLoaderPrivate::PluginList::iterator it = d->pluginList.begin(); 
         it != d->pluginList.end(); ++it)
    {
        if ((*it).first == name )
            return (*it).second;
    }
           
    return 0;
}

ImagePlugin* ImagePluginLoader::pluginInstance(const TQString& libraryName)
{
    KTrader::OfferList offers = KTrader::self()->query("Digikam/ImagePlugin");
    KTrader::OfferList::ConstIterator iter;
    
    for(iter = offers.begin(); iter != offers.end(); ++iter)
    {
        KService::Ptr service = *iter;

        if(service->library() == libraryName)
        {
            return ( pluginIsLoaded(service->name()) );
        }
    }
    
    return 0;
}

bool ImagePluginLoader::pluginLibraryIsLoaded(const TQString& libraryName)
{
    KTrader::OfferList offers = KTrader::self()->query("Digikam/ImagePlugin");
    KTrader::OfferList::ConstIterator iter;
    
    for(iter = offers.begin(); iter != offers.end(); ++iter)
    {
        KService::Ptr service = *iter;

        if(service->library() == libraryName)
        {
            if( pluginIsLoaded(service->name()) )
                return true;
        }
    }
    
    return false;
}

TQPtrList<ImagePlugin> ImagePluginLoader::pluginList()
{
    TQPtrList<ImagePlugin> list;

    for (ImagePluginLoaderPrivate::PluginList::iterator it = d->pluginList.begin(); 
         it != d->pluginList.end(); ++it)
    {
        list.append((*it).second);
    }
        
    return list;
}

}  // namespace Digikam
