/*
 * Copyright (C) 2004 Robert Hogan <robert at roberthogan dot net>
 */

#include "klamav.h"
#include "freshklam.h"
#include "klamd.h"
#include "sigtool.h"
#include "klamscan.h"
#include "kuarantine.h"
#include "aboutklamav.h"
#include "dbviewer.h"
#include "activityviewer.h"
#include "version.h"
#include "firstrunwizard.h"
#include "collectiondb.h"
#include "configdialog.h"
#include "klamavconfig.h"

#include <tdelocale.h>


#include <tdeaction.h>
#include <tqpushbutton.h>
#include <tqlayout.h>
#include <ksystemtray.h>
#include <tdepopupmenu.h>
#include <kdebug.h>
#include <tdemessagebox.h>
#include <kurl.h>

#include <tqdir.h>
#include <tqfile.h>

Klamav *tdemain = 0L;



Klamav::Klamav()
    : TDEMainWindow( 0, "KlamAV " )
{

	downloadDBForWizard = false;
	downloadClamAVForWizard = false;

	tdemain = this;
	TQVBoxLayout *top = new TQVBoxLayout(this,10,10);
	tab = new TQTabWidget(this);
	
  	_tray = new KSystemTray(tdemain, "klamav tray");
	_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));
	connect(_tray,SIGNAL(quitSelected()),SLOT(shuttingDown()));
	
	TDEPopupMenu *conf_menu = _tray->contextMenu();
    EnableKlamd = new TDEAction(i18n("&Enable Auto-Scan"), "klamav_on_acc_enabled", 0,this, SLOT(contextEnable()),actionCollection(),"klamd_enable");
    DisableKlamd = new TDEAction(i18n("&Disable Auto-Scan"),"klamav_on_acc_disabled", 0,this, SLOT(contextDisable()),actionCollection(),"klamd_disable");
        
	EnableFreshklam = new TDEAction(i18n("&Enable Auto-Updates"), "klamav", 0,this, SLOT(contextEnableFK()),actionCollection(),"fk_enable");
    DisableFreshklam = new TDEAction(i18n("&Disable Auto-Updates"),"klamavbw", 0,this, SLOT(contextDisableFK()),actionCollection(),"fk_disable");

	EnableFreshklam->plug(conf_menu);
	DisableFreshklam->plug(conf_menu);
	EnableKlamd->plug(conf_menu);
	DisableKlamd->plug(conf_menu);
	
	TQToolTip::add( _tray, i18n( "KlamAV - Virus Protection for KDE" ) );
	_tray->show();
	
	DisableFreshklam->setEnabled(FALSE);
	EnableFreshklam->setEnabled(TRUE);
	DisableKlamd->setEnabled(FALSE);
	EnableKlamd->setEnabled(TRUE);

        TDEConfig* config = TDEGlobal::config();
        config->setGroup("Freshklam");
        TQStringList DatabasePaths = config->readListEntry("lastDownloadPaths");

        config->setGroup("Kuarantine");
        TQStringList QuarantinePaths = config->readListEntry("KuarantineLocations");

	if ((DatabasePaths.isEmpty()) && (QuarantinePaths.isEmpty())){

            firstRunWizard();
        }

	activityviewer = new Activityviewer(this);

	klamscan = new Klamscan(this);
	tab->addTab(klamscan, i18n("&Scan"));

	klamd = new Klamd(this);
	tab->addTab(klamd, i18n("&Auto-Scan"));

	connect(klamd->search_button,SIGNAL(clicked()),SLOT(contextEnable()));
	connect(klamd->cancel_button,SIGNAL(clicked()),SLOT(contextDisable()));

		
	freshklam = new Freshklam(this);
	tab->addTab(freshklam, i18n("&Update"));

	connect(freshklam->search_button,SIGNAL(clicked()),SLOT(contextUpdateFK()));
	connect(freshklam->cancel_button,SIGNAL(clicked()),SLOT(contextDisableFK()));
	
	sigtool = new Sigtool(this);
	tab->addTab(sigtool, i18n("&E-Mail Protection"));
	
	
	kuarantine = new Kuarantine(this);
	tab->addTab(kuarantine, i18n("&Quarantine"));

	klamdb = new KlamDB(this);
	tab->addTab(klamdb, i18n("Virus Browser"));

	tab->addTab(activityviewer, i18n("Events"));
	
	aboutklamav = new Aboutklamav(this);
	tab->addTab(aboutklamav, i18n("Abou&t"));
	
  


	top->addWidget(tab);
	
	
	connect(tab,SIGNAL(currentChanged ( TQWidget * ) ),klamdb,SLOT(shouldIShow(TQWidget *)));

	KStdAction::quit(this, SLOT(shuttingDown()), actionCollection());
  
  	if (TDEApplication::kApplication()->isRestored()){
/*		config = TDEGlobal::config();
		config->setGroup("Klamd");
		TQString RunKlamd = config->readEntry("Enabled");
		
		if (RunKlamd == "Yes"){
			_tray->setPixmap(KSystemTray::loadIcon("klamav"));
			DisableKlamd->setEnabled(TRUE);
			EnableKlamd->setEnabled(FALSE);

		}
*/
		hide();
	}else{
		show();
   	}

	
	if ((firstDownload) || (downloadDBForWizard)){
		kdDebug() << "firstdownload" << firstDownload << endl;
		kdDebug() << "downloadDBForWizard" << downloadDBForWizard << endl;
		tab->setCurrentPage(2);
		freshklam->slotSearch();
	}
        if (downloadClamAVForWizard)
            freshklam->checkForNewClamAVNow();
	//klamdb->shouldIShow();

	CollectionDB::instance()->insertEvent("Launch","KlamAV Launched");

    setCaption(TQString("KlamAV %1 (Using ClamAV %2)").arg(KLAMAV_VERSION).arg(KlamavConfig::clamAVVersion()));
}
	
Klamav::~Klamav()
{
    KlamavConfig::writeConfig();
	kapp->quit();
}

void  Klamav::shuttingDown(){

	this->topLevelWidget()->hide();

}

bool Klamav::queryClose() {
	if ((klamd->isKlamdAlive()) || (freshklam->isFreshklamAlive())){
        KMessageBox::information (this,i18n("<p>KlamAV will stay open in the system tray. <br><br>"
        " <b>Remember</b> - you can't close KlamAV while <br> auto-scanning "
        " and/or auto-updating are still running!</p>"),"KlamAV","dontshow");
		hide();
		return false;

	}
	return true;
}


void Klamav::contextEnable() {
	
	klamd->startKlamd();
	//if (klamd->startKlamd()){
			//_tray->setPixmap(KSystemTray::loadIcon("klamav"));
			//EnableKlamd->setEnabled(FALSE);
			//DisableKlamd->setEnabled(TRUE);
	//}
}

void Klamav::clamdStopped() {
/*	if (freshklam->isFreshklamAlive())
		_tray->setPixmap(KSystemTray::loadIcon("klamavbwdl"));
	else*/
	_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));
	DisableKlamd->setEnabled(FALSE);
	EnableKlamd->setEnabled(TRUE);
}

void Klamav::contextDisable() {
	klamd->slotCancel();
    resetAutoScan();
}

void Klamav::resetAutoScan() {
/*	if (freshklam->isFreshklamAlive())
		_tray->setPixmap(KSystemTray::loadIcon("klamavbwdl"));
	else*/
	_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));
	DisableKlamd->setEnabled(FALSE);
	EnableKlamd->setEnabled(TRUE);
}


void Klamav::contextUpdateFK() {

    freshklam->slotSearch();
}

void Klamav::contextEnableFK() {

    freshklam->enableAutoUpdates();
}

void Klamav::contextDisableFK() {
	
	freshklam->slotCancel();
// 	DisableFreshklam->setEnabled(FALSE);
// 	EnableFreshklam->setEnabled(TRUE);

}
void Klamav::showVirusBrowser() {
	tab->setCurrentPage(5);
}

void Klamav::firstRunWizard() {

        FirstRunWizard wizard;
        wizard.setCaption( i18n( "First-Run Wizard" ));
        
        TQString homepath = getenv("HOME");
        TQString defaultdb = homepath + "/.klamav/database";
        TQString defaultquar = homepath + "/.klamav/quarantine";
        if( wizard.exec() != TQDialog::Rejected ){
    
            TDEConfig* config = TDEGlobal::config();

            config->setGroup("Freshklam");
            
            TQString wizardDBPath = wizard.databasePath().path(-1);
            TQString wizardTQRPath = wizard.quarantinePath().path(-1);
/*            kdDebug() << wizard.databasePath() << endl;
            kdDebug() << wizard.defaultDatabasePath() << endl;*/
            //Configure Database Path
            TQStringList lastDownloadPaths;
            if ((wizardDBPath != "") && (TQDir::cleanDirPath(wizardDBPath) != defaultdb)){
                lastDownloadPaths.prepend( TQString("%1").arg(wizardDBPath));
                checkDir(wizardDBPath);
            }else{
                lastDownloadPaths.prepend( TQString("%1").arg(wizard.defaultDatabasePath()));
                createDefaultKlamAVDir("database");
            }
            config->writeEntry("lastDownloadPaths", lastDownloadPaths);
            config->sync();
            //Configure Quarantine Path
            TQStringList lastQuarLocations;
        
            config->setGroup("Kuarantine");
            
/*            kdDebug() << wizard.quarantinePath() << endl;
            kdDebug() << wizard.defaultQuarantinePath() << endl;
            kdDebug() << defaultquar << endl;*/
            if ((wizardTQRPath != "") && (TQDir::cleanDirPath(wizardTQRPath) != defaultquar)){
                lastQuarLocations.prepend( TQString("%1").arg(wizardTQRPath));
                checkDir(wizardTQRPath);
            }else{
                lastQuarLocations.prepend( TQString("%1").arg(wizard.defaultQuarantinePath()));
                createDefaultKlamAVDir("quarantine");
            }
            config->writeEntry("KuarantineLocations", lastQuarLocations);
            config->sync();

            if (wizard.downloadDatabase()){
                kdDebug() << "downloading database" << endl;
                downloadDBForWizard = true;
            }
            if (wizard.downloadClamAV()){
                kdDebug() << "downloading clamav" << endl;
                downloadClamAVForWizard = true;
            }

        }

}

void  Klamav::createDefaultKlamAVDir(TQString type){

    TQString path = getenv("HOME");
    bool ok = true;
    // directory exist?
    path += "/.klamav";
    TQDir klamavdir(path);
    if (!klamavdir.exists() && !klamavdir.mkdir(path))
        ok = false;

    path += "/" + type;
    if (ok)
    {
        TQDir klamavqdir(path);
        if (!klamavqdir.exists() && !klamavqdir.mkdir(path))
            ok = false;
        else
            chmod((const char *)path,0700);
    }

}

void  Klamav::checkDir(TQString path){

    TQDir klamavdir(path);
    TQFile f1( path );
    if ((!klamavdir.exists()) || (f1.open( IO_ReadWrite )))
        KMessageBox::information(this, i18n("Either the directory %1 does not exist or you are not able to write to it. Either way, you will have to change it as it cannot be used. Sorry!").arg(path));
    f1.close(); 

}

void Klamav::slotConfigKlamav( const TQCString& page )
{

    KlamavConfigDialog* dialog = (KlamavConfigDialog*) TDEConfigDialog::exists( "settings" );

    if( !dialog )
    {
        //TDEConfigDialog didn't find an instance of this dialog, so lets create it :
        dialog = new KlamavConfigDialog( this, "settings", KlamavConfig::self() );
        //connect( dialog, SIGNAL(settingsChanged()), SLOT(applySettings()) );
    }

    //FIXME it seems that if the dialog is on a different desktop it gets lost
    //      what do to? detect and move it?

    dialog->show();
    dialog->raise();
    dialog->setActiveWindow();

    //so that if the engine page is needed to be shown it works

    if ( !page.isNull() ) dialog->showPage( page );
}


#include "klamav.moc"
