/*
This file is part of the KDE project
Copyright (C) 2004 Martijn Klingens <klingens@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.

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.

You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/

#include <qlayout.h>
#include <qwhatsthis.h>
#include <qvgroupbox.h>
#include <qpushbutton.h>
#include <qheader.h>
#include <qtimer.h>
#include <qfileinfo.h>

#include <kaboutdata.h>
#include <kapplication.h>
#include <kdesktopfile.h>
#include <kdialog.h>
#include <kgenericfactory.h>
#include <klistview.h>
#include <kmessagebox.h>
#include <kservice.h>
#include <kstandarddirs.h>

#include <dcopclient.h>
#include <dcopref.h>

#include <kdebug.h>

#include "kcmautostart.h"
#include "kcmautostart.moc"

typedef KGenericFactory<AutoStartConfig, QWidget> AutoStartFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_autostart, AutoStartFactory( "kcmautostart" ) )

AutoStartConfig::AutoStartConfig(QWidget* parent, const char* name, const QStringList &) :
    KCModule( AutoStartFactory::instance(), parent, name )
{
    KGlobal::dirs()->addResourceType("autostart", "share/autostart");
    KAboutData *about =
        new KAboutData( I18N_NOOP( "kcmautostart" ), I18N_NOOP( "KDE Service Manager" ),
            0, 0, KAboutData::License_GPL, I18N_NOOP( "(c) 2004 Martijn Klingens" ) );
    about->addAuthor( "Martijn Klingens", 0, "klingens@kde.org" );

#if KDE_IS_VERSION(3,2,91)
    setAboutData( about );
#endif

    QVBoxLayout *lay = new QVBoxLayout( this, 0, KDialog::spacingHint() );

    QGroupBox *gb = new QVGroupBox( i18n( "Startup Services" ), this );
    QWhatsThis::add(gb, i18n("This shows all KDE services that can be loaded "
                "on KDE startup. Checked services will be invoked on next startup. "
                "Be careful with deactivation of unknown services."));
    lay->addWidget( gb );

    _lvStartup = new KListView( gb );
    _lvStartup->addColumn(i18n("Use"));
    _lvStartup->addColumn(i18n("Service"));
    _lvStartup->addColumn(i18n("Description"));
    _lvStartup->setAllColumnsShowFocus(true);
    _lvStartup->header()->setStretchEnabled(true, 2);

    load();
}

void setModuleGroup(KConfig *config, const QString &filename)
{
    QString module = filename;
    int i = module.findRev('/');
    if (i != -1)
    module = module.mid(i+1);
    i = module.findRev('.');
    if (i != -1)
    module = module.left(i);

    config->setGroup(QString("Module-%1").arg(module));
}

bool AutoStartConfig::autoloadEnabled(KConfig *config, const QString &filename)
{
    setModuleGroup(config, filename);
    return config->readBoolEntry("autoload", true);
}

void AutoStartConfig::setAutoloadEnabled(KConfig *config, const QString &filename, bool b)
{
    setModuleGroup(config, filename);
    return config->writeEntry("autoload", b);
}

void AutoStartConfig::load() {
    _lvStartup->clear();

    QStringList files = KGlobal::dirs()->findAllResources( "autostart", QString::fromLatin1( "*.desktop" ), false, true );

    for ( QStringList::ConstIterator it = files.begin(); it != files.end(); it++ )
    {
        if ( KDesktopFile::isDesktopFile( QFileInfo( *it ).fileName() ) )
        {
            KDesktopFile file( QFileInfo( *it ).fileName(), true, "autostart" );
            QString name = file.readName();
            if ( !name.isEmpty() )
            {
                CheckListItem *clitem = new CheckListItem( _lvStartup, QString::null );
                connect( clitem, SIGNAL( changed( QCheckListItem * ) ), SLOT( slotItemChecked( QCheckListItem * ) ) );
                clitem->setText( 1, name );
                clitem->setText( 2, file.readComment() );
                clitem->setText( 3, *it );
                clitem->setOn( !file.readBoolEntry( "Hidden", false ) );
            }
        }
    }
}

void AutoStartConfig::save()
{
    QListViewItemIterator it( _lvStartup );
    while ( it.current() )
    {
        if ( KDesktopFile::isDesktopFile( it.current()->text( 3 ) ) )
        {
            // Determine whether we need to change the file on a readonly desktop file
            // by giving a full path first
            QString path = it.current()->text( 3 );
            KDesktopFile file( path, true, "services" );
            bool shouldBeHidden = !( static_cast<QCheckListItem *>( it.current() )->isOn() );
            if ( file.readBoolEntry( "Hidden", false ) != shouldBeHidden )
            {
                KDesktopFile outFile( QFileInfo( path ).fileName(), false, "autostart" );
                kdDebug() << "************** Writing out " << path << endl;
                outFile.writeEntry( "Hidden", shouldBeHidden );
                outFile.sync();
            }
        }
        ++it;
    }

    //QTimer::singleShot(0, this, SLOT(slotServiceRunningToggled()));
}

void AutoStartConfig::defaults()
{
    QListViewItemIterator it( _lvStartup);
    while ( it.current() != 0 ) {
        if (it.current()->rtti()==1) {
            QCheckListItem *item = static_cast<QCheckListItem *>(it.current());
            item->setOn(false);
        }
        ++it;
    }
}

void AutoStartConfig::slotReload()
{
    QString current = _lvStartup->currentItem()->text(4);
    load();
    QListViewItem *item = _lvStartup->findItem(current, 4);
    if (item)
        _lvStartup->setCurrentItem(item);
}

void AutoStartConfig::slotItemChecked(QCheckListItem*)
{
    emit changed(true);
}

QString AutoStartConfig::quickHelp() const
{
    return i18n("<h1>Service Manager</h1><p>This module allows you to have an overview of all plugins of the "
            "KDE Daemon, also referred to as KDE Services. Generally, there are two types of service:</p>"
            "<ul><li>Services invoked at startup</li><li>Services called on demand</li></ul>"
            "<p>The latter are only listed for convenience. The startup services can be started and stopped. "
            "In Administrator mode, you can also define whether services should be loaded at startup.</p>"
            "<p><b> Use this with care: some services are vital for KDE; do not deactivate services if you"
            " do not know what you are doing.</b></p>");
}

CheckListItem::CheckListItem(QListView *parent, const QString &text)
    : QObject(parent),
    QCheckListItem(parent, text, CheckBox)
{ }

void CheckListItem::stateChange(bool on)
{
    QCheckListItem::stateChange(on);
    emit changed(this);
}
