/***************************************************************************
 *   Copyright (C) 2003 by liuspider                                       *
 *   liuspider@users.sourceforge.net                                       *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#define Uses_SCIM_CONFIG_PATH

#include "scimimenginesettings.h"

#include <qlistview.h> 
#include <qpixmap.h> 
#include <qiconset.h> 
#include <kgenericfactory.h>
#include <klocale.h>

typedef KGenericFactory<ScimIMEngineSettings> KCMScimIMEngSettingsLoaderFactory;

K_EXPORT_COMPONENT_FACTORY( kcm_skimplugin_scim_imengines, 
    KCMScimIMEngSettingsLoaderFactory( "kcm_skimplugin_scim_imengines" ) )

class ScimIMEngineSettings::ScimIMEngineSettingsPrivate {
public:
    struct itemExtraInfo{
        bool enabled;
        int uuidIndex;
    };
    QMap<QCheckListItem*, itemExtraInfo> itemInfos;
    QStringList uuids;
};
ScimIMEngineSettings::ScimIMEngineSettings(QWidget *parent, 
  const char */*name*/, const QStringList &args)
 : KAutoCModule( KCMScimIMEngSettingsLoaderFactory::instance(), parent, args ),
   d(new ScimIMEngineSettingsPrivate)
{
    listView = new QListView(this);
    setMainWidget(listView);
    listView->addColumn( i18n("Name") );
    listView->setRootIsDecorated(true);
    connect(listView, SIGNAL(clicked(QListViewItem *)), SLOT(checkBoxModified(QListViewItem*)));
    load();
}

// ScimIMEngineSettings::~ScimIMEngineSettings(){}
#define PIX_COLUMN 0
void ScimIMEngineSettings::load() {
    clear();

    QStringList & uuids = d->uuids;
    QStringList names;
    QStringList langs;
    std::vector <scim::String> icons;
    
    std::map <QString, std::vector <size_t> > groups;
    
    QString      lang_name;
    size_t i;
    
    get_factory_list (uuids, names, langs, icons);

    for (i = 0; i < uuids.size (); ++i) {
        groups [langs [i]].push_back (i);
    }
    
    // Add language group
    for (std::map <QString, std::vector <size_t> >::iterator it = groups.begin ();
         it != groups.end (); ++ it) {
        scim::String raw_name(it->first.utf8());
        lang_name = QString::fromUtf8(scim::scim_get_language_name (raw_name).c_str());
        QCheckListItem * langGroupItem = 
          new QCheckListItem(listView, lang_name, QCheckListItem::CheckBoxController);

        // Add factories for this group
//         bool inconsistent = false;
        std::vector<scim::String> disabled;
        disabled = scim::scim_global_config_read (
            scim::String (SCIM_GLOBAL_CONFIG_DISABLED_IMENGINE_FACTORIES), disabled);
        QString disabledFactories = QString::fromLatin1(scim::scim_combine_string_list(disabled).c_str());
        for (i = 0; i < it->second.size (); ++i) {
          QCheckListItem * item =
            new QCheckListItem(langGroupItem, names [it->second [i]], QCheckListItem::CheckBox);
          ScimIMEngineSettingsPrivate::itemExtraInfo info = {false, it->second [i]};
          QPixmap * p = new QPixmap(icons [it->second [i]].c_str ());
          QIconSet * icon = new QIconSet(*p);
          pixmaps.push_back(p);
          iconsets.push_back(icon);
          item->setPixmap(PIX_COLUMN, icon->pixmap(QIconSet::Automatic, QIconSet::Normal));
          if(!disabledFactories.contains(uuids[it->second [i]])) {
            item->setOn(true);
            info.enabled = true;
          }
          d->itemInfos[item] = info;
//             inconsistent = true;
        }
//         if(inconsistent)
//           langGroupItem->setState(QCheckListItem::NoChange);
    }
}

void ScimIMEngineSettings::save()
{
    std::vector<scim::String> disabledUUIDsList;
    QCheckListItem * item;
    QListViewItemIterator it(listView, QListViewItemIterator::NotChecked);
    while ( it.current() ) {
        if((item = dynamic_cast<QCheckListItem *>(it.current()))) {
          if(d->itemInfos.contains(item)) {
            disabledUUIDsList.push_back(d->uuids[d->itemInfos[item].uuidIndex].latin1());
          }
        }
        it++;
    }
    
    scim::scim_global_config_write (
        scim::String (SCIM_GLOBAL_CONFIG_DISABLED_IMENGINE_FACTORIES), disabledUUIDsList);
}

void ScimIMEngineSettings::defaults()
{
    QCheckListItem * item;
    QListViewItemIterator it(listView);
    while ( it.current() ) {
        if((item = dynamic_cast<QCheckListItem *>(it.current()))) {
          item->setOn(true);
        }
        it++;
    }
}

void ScimIMEngineSettings::checkBoxModified(QListViewItem * curit)
{
    if(!curit)
      return;
      
    QCheckListItem * item;
    if(!(item = dynamic_cast<QCheckListItem *>(curit)))
      return;
      
    if(item->type() != QCheckListItem::CheckBox 
        && item->type() != QCheckListItem::CheckBoxController )
      return;

    QListViewItemIterator it(listView/*, QListViewItemIterator::Checked*/);
    while ( it.current() ) {
        if((item = dynamic_cast<QCheckListItem *>(it.current()))) {
          if(d->itemInfos.contains(item)) {
            if(item->isOn() != d->itemInfos[item].enabled) {
              emit changed(true);
              break;
            }
          }
        }
        it++;
    }
    if(!it.current())
      emit changed(false);
}

ScimIMEngineSettings::~ScimIMEngineSettings()
{
    clear();
}
void ScimIMEngineSettings::clear()
{
    d->itemInfos.clear();
    listView->clear();
    for(uint i = 0; i < iconsets.size(); i++)
      delete iconsets[i];
    for(uint i = 0; i < pixmaps.size(); i++)
      delete pixmaps[i];
    iconsets.clear();
    pixmaps.clear();
}
void ScimIMEngineSettings::get_factory_list (QStringList &uuids,
                          QStringList &names,
                          QStringList &langs,
                          std::vector <scim::String> &icons)
{
    std::vector<scim::String>    module_list;
    scim::IMEngineFactoryPointer factory;
    scim::IMEngineModule         module;
    scim::ConfigPointer          config;

    scim::scim_get_imengine_module_list (module_list);

    uuids.clear ();
    names.clear ();
    langs.clear ();
    icons.clear ();
    scim::ConfigModule * cmodule = new scim::ConfigModule ("kconfig");
    if (cmodule && cmodule->valid ()) {
        m_config = cmodule->create_config ("scim");
        if (m_config.null ()) {
            std::cerr << "  Failed to load Config Module 'kconfig'\n";
        }
    }
    
    
    if (!m_config.null ()) config = m_config;
    else config = new scim::DummyConfig ("scim");

    for (size_t i = 0; i < module_list.size (); ++ i) {
        module.load (module_list [i], config);
        if (module.valid ()) {
            for (size_t j = 0; j < module.number_of_factories (); ++j) {
                //FIXME
//                 try {
                    factory = module.create_factory (j);
//                 } catch (...) {
//                     factory.reset ();
//                 }

                if (!factory.null ()) {
                    if (uuids.find(QString::fromLatin1(factory->get_uuid ().c_str())) == uuids.end ()) {
                        uuids.push_back (QString::fromLatin1(factory->get_uuid ().c_str()));
                        names.push_back (
                          QString::fromUtf8(scim::utf8_wcstombs (factory->get_name ()).c_str()));
                        langs.push_back (QString::fromUtf8(
                          scim::scim_get_normalized_language (factory->get_language ()).c_str()));
                        icons.push_back (factory->get_icon_file ());
                    }
                    factory.reset ();
                }
            }
            module.unload ();
        }
    }
}

#include "scimimenginesettings.moc"
