/***************************************************************************
 *   Copyright (C) 2006 by Stephen Leaf                                    *
 *   smileaf@smileaf.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; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

/* Adapted for use in the Trinity Desktop Environment */

#include <tqlayout.h>

#include <tdelocale.h>
#include <tdeglobal.h>
#include <tdeparts/genericfactory.h>
#include <ksimpleconfig.h>
#include <tdeglobalsettings.h>
#include <kstandarddirs.h>
#include <kurlrequester.h>
#include <tdelistview.h>
#include <kopenwith.h>
#include <kpropertiesdialog.h>
#include <tdeio/job.h>
#include <tqdir.h>
#include <tqheader.h>
#include <tdemessagebox.h>
#include "autostart.h"

class CDesktopItem : public TDEListViewItem {

public:
  KService *mService;
  KURL fileName;
  int iStartOn;
  enum { AutoStart, Shutdown, ENV };

	CDesktopItem( TQString service, int startOn, TQListView *parent ): TDEListViewItem( parent ),
	  mService(NULL), iStartOn(startOn), fileName(KURL(service))
	{
		if (service.endsWith(".desktop")) {
			mService = new KService(service);
		}
	}

	~CDesktopItem() {
		if (mService) {
			delete mService;
			mService = NULL;
		}
	}

	TQString fStartOn() {
		switch (iStartOn) {
			case AutoStart:
				return i18n("Startup");
				break;
			case Shutdown:
				return i18n("Shutdown");
				break;
			case ENV:
				return i18n("ENV");
				break;
			default:
				return "";
				break;
		}
	}

	void setStartOn(int start) {
		iStartOn = start;
		setText(2, fStartOn());
		TQString path;
		switch (iStartOn) {
			case AutoStart:
				path = TDEGlobalSettings::autostartPath()+"/";
				break;
			case Shutdown:
				path = TDEGlobal::dirs()->localtdedir()+"shutdown/";
				break;
			case ENV:
				path = TDEGlobal::dirs()->localtdedir()+"env/";
				break;
		}
		TDEIO::file_move(fileName, KURL( path + fileName.fileName() ));
		fileName = path + fileName.fileName();
	}

	void updateService() {
		if (mService) {
			delete mService;
			mService = NULL;
		}
		mService = new KService( fileName.path() );
		setText( 0, mService->name() );
		setText( 1, mService->exec() );
		setText( 2, fStartOn() );
	}

};  //class CDesktopItem

typedef KGenericFactory<CAutostart, TQWidget> autostartFactory;

K_EXPORT_COMPONENT_FACTORY( kcm_autostart, autostartFactory("kcmautostart"))

CAutostart::CAutostart(TQWidget *parent, const char *name, const TQStringList&)
    : TDECModule(parent, name), myAboutData(0)
{
  TQGridLayout * AutostartConfigLayout = new TQGridLayout( this, 1, 1, 11, 6, "AutostartConfigLayout");

  btnAdd = new KPushButton( this, "btnAdd" );
  AutostartConfigLayout->addWidget( btnAdd, 0, 1 );

  listCMD = new TDEListView( this, "listCMD" );
  listCMD->addColumn( i18n( "Name" ) );
  listCMD->addColumn( i18n( "Command" ) );
  listCMD->addColumn( i18n( "Run on" ) );
  listCMD->setAllColumnsShowFocus( true );
  listCMD->setShowSortIndicator( true );

  AutostartConfigLayout->addMultiCellWidget( listCMD, 0, 4, 0, 0 );
  TQSpacerItem * spacer1 = new TQSpacerItem( 71, 170, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
  AutostartConfigLayout->addItem( spacer1, 4, 1 );

  btnRemove = new KPushButton( this, "btnRemove" );
  AutostartConfigLayout->addWidget( btnRemove, 1, 1 );

  btnProperties = new TQPushButton( this, "btnProperties" );
  AutostartConfigLayout->addWidget( btnProperties, 2, 1 );

  cmbStartOn = new TQComboBox( this, "cmbStartOn" );
  AutostartConfigLayout->addWidget( cmbStartOn, 3, 1 );

  cmbStartOn->insertItem( i18n("Startup") );
  cmbStartOn->insertItem( i18n("Shutdown") );
  cmbStartOn->insertItem( i18n("ENV") );
  cmbStartOn->setEnabled(false);

  btnAdd->setText( i18n( "&Add" ) );
  btnRemove->setText( i18n( "&Remove" ) );
  btnProperties->setText( i18n( "&Properties" ) );

  connect( btnAdd, TQ_SIGNAL(clicked()), TQ_SLOT(addCMD()) );
  connect( btnRemove, TQ_SIGNAL(clicked()), TQ_SLOT(removeCMD()) );
  connect( listCMD, TQ_SIGNAL(doubleClicked(TQListViewItem*)), TQ_SLOT(editCMD() ));
  connect( btnProperties, TQ_SIGNAL(clicked()), TQ_SLOT(editCMD()) );
  connect( cmbStartOn, TQ_SIGNAL(activated(int)), TQ_SLOT(setStartOn(int)) );
  connect( listCMD, TQ_SIGNAL(selectionChanged(TQListViewItem*)), TQ_SLOT(selectionChanged(TQListViewItem*)) );

  listCMD->setFocus();

  load();

  TDEAboutData* about = new TDEAboutData("autostart", I18N_NOOP("TDE Autostart Manager"), "0.5",
    I18N_NOOP("TDE Autostart Manager Control Panel Module"),
    TDEAboutData::License_GPL,
    I18N_NOOP("(c) 2006 Stephen Leaf"), 0, 0);

  about->addAuthor("Stephen Leaf", 0, "smileaf@smileaf.org");
  setAboutData( about );

};


CAutostart::~CAutostart()
{}

void CAutostart::load()
{
  kdDebug() << "According to TDE your Autostart location is: " << TDEGlobalSettings::autostartPath() << endl;

  TQString path;
  for (int x=0;x<3;x++) {
    if (x==0)
      path = TDEGlobalSettings::autostartPath();
    else if (x==1)
      path = TDEGlobal::dirs()->localtdedir() + "/shutdown";
    else if (x==2)
      path = TDEGlobal::dirs()->localtdedir() + "/env";

    if (!TDEStandardDirs::exists(path))
      TDEStandardDirs::makeDir(path);

    TQDir *autostartdir = new TQDir( path );
    autostartdir->setFilter( TQDir::Files);
    const TQFileInfoList *list = autostartdir->entryInfoList();
    TQFileInfoListIterator it( *list );
    TQFileInfo *fi;
    while ( (fi = it.current()) != 0 ) {
      TQString filename = fi->fileName();
      CDesktopItem *item = new CDesktopItem( fi->absFilePath(), x, listCMD );
      if ( !item->mService ) {
        if ( fi->isSymLink() ) {
          TQString link = fi->readLink();
          item->setText( 0, filename );
          item->setText( 1, link );
          item->setText( 2, item->fStartOn() );
        }
        else {
          item->setText( 0, filename );
          item->setText( 1, filename );
          item->setText( 2, item->fStartOn() );
        }
      }
      else {
        item->setText( 0, item->mService->name() );
        item->setText( 1, item->mService->exec() );
        item->setText( 2, item->fStartOn() );
      }
      ++it;
    }
  }
}

void CAutostart::addCMD() {
  KService::Ptr service = 0L;
  KOpenWithDlg owdlg( this );
  if (owdlg.exec() != TQDialog::Accepted)
    return;
  service = owdlg.service();

  Q_ASSERT(service);
  if (!service)
    return; // Don't crash if KOpenWith wasn't able to create service.

  KURL desktopTemplate;
	
	if ( service->type() == "Service") {
    KMessageBox::error(0, i18n("Cannot add a Service entry to the list of autostart modules.\n") + service->desktopEntryPath());
		return;
	}
  else if ( service->desktopEntryName().isNull() ) {
    desktopTemplate = KURL( TDEGlobalSettings::autostartPath() + service->name() + ".desktop" );
    KSimpleConfig ksc(desktopTemplate.path());
    ksc.setGroup("Desktop Entry");
    ksc.writeEntry("Encoding","UTF-8");
    ksc.writeEntry("Exec",service->exec());
    ksc.writeEntry("Icon","application-x-executable");
    ksc.writeEntry("Path","");
    ksc.writeEntry("Terminal",false);
    ksc.writeEntry("Type","Application");
    ksc.sync();

    KPropertiesDialog *dlg = new KPropertiesDialog( desktopTemplate, this, 0, true /*modal*/, false /*no auto-show*/ );
    if ( dlg->exec() != TQDialog::Accepted )
      return;
  }
  else {
    desktopTemplate = KURL( locate("apps", service->desktopEntryPath()) );
		// Make sure the URL is not empty to avoid crashing the application
		if (desktopTemplate.isEmpty()) {
      KMessageBox::error(0, i18n("Can't find a matching entry for the selected item.\n") + service->desktopEntryPath());
			return;
		}
		
    KPropertiesDialog *dlg = new KPropertiesDialog( desktopTemplate, KURL(TDEGlobalSettings::autostartPath()),
      service->name() + ".desktop", this, 0, true /*modal*/, false /*no auto-show*/ );
    if ( dlg->exec() != TQDialog::Accepted )
      return;
  }

  CDesktopItem * item = new CDesktopItem( TDEGlobalSettings::autostartPath() + service->name() + ".desktop", CDesktopItem::AutoStart, listCMD );
  item->setText( 0, item->mService->name() );
  item->setText( 1, item->mService->exec() );
  item->setText( 2, item->fStartOn() );
  emit changed(true);
}

void CAutostart::removeCMD() {
  if (!listCMD->selectedItem())
    return;

	TQListViewItem *currItem = listCMD->selectedItem();
  TDEIO::del(((CDesktopItem *)currItem)->fileName);
  listCMD->takeItem(currItem);
  delete currItem;
  
  kdDebug() << "Deleting file" << endl;
  emit changed(true);
}

void CAutostart::editCMD() {
  CDesktopItem *currItem = (CDesktopItem*)(listCMD->selectedItem());
  if (!currItem) return;
  	
  KFileItem kfi = KFileItem(KFileItem::Unknown, KFileItem::Unknown, KURL(currItem->fileName), true);
  if (!editCMD(kfi)) return;

	currItem->updateService();
}

bool CAutostart::editCMD( KFileItem item) {
  KPropertiesDialog *dlg = new KPropertiesDialog(&item, this);
  if ( dlg->exec() != TQDialog::Accepted )
    return false;
  
  kdDebug() << "Saving file" << endl;
  emit changed(true);
  return true;
}

void CAutostart::setStartOn( int index ) {
  ((CDesktopItem*)listCMD->currentItem())->setStartOn(index);
}

void CAutostart::selectionChanged(TQListViewItem* entry) {
  cmbStartOn->setEnabled( (entry != 0) );
  cmbStartOn->setCurrentItem( ((CDesktopItem*)entry)->iStartOn );
}

void CAutostart::defaults(){}

void CAutostart::save(){}

int CAutostart::buttons()
{
  return TDECModule::Apply|TDECModule::Help;
}

TQString CAutostart::quickHelp() const
{
  return i18n("This module helps configure which applications TDE runs when starting and exiting.");
}

#include "autostart.moc"
