//
// C++ Implementation: c6pluginmanager
//
// Description:
//
//
// Author: Giorgio A. <openc6@hotmail.com>, (C) 2005
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "c6pluginmanager.h"
#include <qstringlist.h>
#include <qlibrary.h>

SOManager::SOManager()
{}

void SOManager::addLibrary(QString const &fname)
{
    QLibrary *library = new QLibrary(fname);   

    if (library == 0)
    {
        qWarning("Error in opening library %s\n",fname.latin1());
    }
    else
    {
        _soHandle.insert(fname,library);
    }
}

void SOManager::removeLibrary(QString const &fname)
{
    HandleMap::Iterator it = _soHandle.find(fname);   
    
    if (it != _soHandle.end())
    {
        QLibrary* library = it.data();
        delete library;
        _soHandle.remove(it);     
    }
}

SOManager::~SOManager()
{
    for(HandleMap::Iterator it=_soHandle.begin(); it != _soHandle.end(); it++)
    {
        QLibrary* library = it.data();
        delete library;    
    }
}

QLibrary* SOManager::getHandle(QString const &fname)
{
    HandleMap::Iterator it = _soHandle.find(fname);
    if (it != _soHandle.end())
    {              
        return(it.data());
    }      
    
    return(0);   
}

bool SOManager::getSymbol(QLibrary* library,void **symbol,const char *symbolName)
{
    bool ret = true;

    if(library !=0 )
    {
        *symbol = library->resolve(symbolName);
        
        if(*symbol == 0 )
        {
            qWarning("SOManager: error in getting symbol %s\n",symbolName);         
            ret = false;
        }
    }
    else
    {
        qWarning("SOManager :error handle is null\n");             
        ret = false;
    }
    
    return(ret);
}

bool SOManager::getLibrarySymbol(void** out,QString const &fname,QString const &symbolName)
{
    bool ret = false;
    QLibrary *library = getHandle(fname);

    if (library != 0)
    {
        ret = getSymbol(library,out,symbolName.latin1());
    }
    else
    {
        qWarning("SOManager: error handle for %s is null \n",fname.latin1());        
    }      
    
    return(ret);
}

SOFactory::SOFactory():
        _soManager(new SOManager())
{}

void SOFactory::addLibrary(QString const &fname)
{
    if (_soManager != 0)
    {         
        _soManager->addLibrary(fname);
        FactoryFunctionType fact;
        
        if (getLibrarySymbol((void**)&fact,fname) == true)
        {         
            _factoryFunction.insert(fname,fact);
        }  
        else
        {
            qWarning("SOfactory: error getting init function\n",fname.latin1());      
        }          
    }
    else
    {
        qWarning("SOfactory: error adding library %s soManager is null\n",fname.latin1());                
    }   
}

void SOFactory::removeLibrary(QString const &fname)
{
    if (_soManager != 0)
    {         
        _soManager->removeLibrary(fname);
     
        FactoryFunction::Iterator it= _factoryFunction.find(fname); 
        _factoryFunction.remove(it);                 
    }      
}

bool SOFactory::getLibrarySymbol(void** out,QString const &fname,const char *symbol)
{
    bool ret = false;   
    if (_soManager != 0)
    {          
        ret = _soManager->getLibrarySymbol(out,fname,symbol ? symbol : "defaultFactoryFunction");
    }
    
    return(ret);   
}

void* SOFactory::getFactory(QString const &fname)
{
    if (exists(fname) == true)
    {
        FactoryFunction::Iterator it= _factoryFunction.find(fname);  
        if (it != _factoryFunction.end())
        {
            return((void*)(*it)());     
        }                          
    }                
    
    return(0);        
}

bool SOFactory::exists(QString const &fname)
{
    FactoryFunction::Iterator it= _factoryFunction.find(fname);    
    return(it != _factoryFunction.end());  
}      

QStringList SOFactory::getFactoryName()
{
    return(_factoryFunction.keys());
}       

SOFactory::~SOFactory()
{
    delete _soManager;     
}

C6PluginManager::C6PluginManager() 
{
    _soFactory = new SOFactory();    
}

C6PluginManager::~C6PluginManager()
{
    delete _soFactory;   
}

C6PlugInFactory* C6PluginManager::getFactory(QString const &fname)
{
    if (_soFactory->exists(fname) == false)
    {  
        _soFactory->addLibrary(fname);
    }      
    
    C6PlugInFactory* tmp = reinterpret_cast<C6PlugInFactory*>(_soFactory->getFactory(fname));   
    return(tmp);    
}

void C6PluginManager::destroy(QString const &fname)
{
    if (_soFactory->exists(fname) == true)
    {  
        _soFactory->removeLibrary(fname);
    }      
}

QStringList C6PluginManager::getFactoryName()
{
    return(_soFactory->getFactoryName());   
}      

