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

#include "klamscan.h"
#include "klamav.h"
#include "klamscanoptions.h"
#include "schedule.h"
#include "directorylist.h"
#include "tabwidget.h"
#include "scanviewer.h"
#include "collectiondb.h"


#include <config.h>
#include <kiconloader.h>
#include <kstatusbar.h>
#include <kdebug.h>
#include <ksystemtray.h>
#include <tdefiledialog.h>


#include <tqpushbutton.h>
#include <tqlayout.h>
#include <tdecmdlineargs.h>
#include <tdemessagebox.h>
#include <tqtooltip.h>
#include <tqtoolbutton.h>
#include <tqstringlist.h>
#include <dcopclient.h>
#include <tqdir.h>
#include <kprogress.h>
#include <dcopref.h>
#include <dcopclient.h>


#include <sys/stat.h> // TDEIO does not seem to have what we need

using namespace KlamAV;

Klamscan::Klamscan(TQWidget *parent, const char *name)
    : TQWidget(parent, name), DCOPObject( "DCOPKlamscan" )
{



/*    scanInProgress = false;
    multiScan = false;    */
    setDefaults();
    TQBoxLayout *top = new TQVBoxLayout(this,10,10);


    tabBrowser = new TabWidget(this, "Klamscan", TQStringList( i18n("Launcher") ));
    tabBrowser->setMargin(5);
    top->addWidget(tabBrowser);


/*    dblayout->addMultiCellWidget( tabBrowser, 0, 1, 1, 1 );*/

    //TQGridLayout *layout = new TQGridLayout(this, 6, 3, 10, 4);
     TQWidget* privateLayoutWidget2 = new TQWidget( this, "dblayout" );

    TQGridLayout *layout = new TQGridLayout(privateLayoutWidget2, 6, 6, 10, 4);
    layout->setColStretch(0, 10);
    layout->addColSpacing(1, 10);
    layout->setColStretch(1, 0);
    layout->setColStretch(2, 1);
    layout->addRowSpacing(1, 10);
    layout->setRowStretch(1, 0);
    layout->setRowStretch(2, 10);
    layout->addRowSpacing(4, 10);
    layout->setRowStretch(4, 0);





    TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();


    TQLabel *combo_label = new TQLabel(i18n("When a virus is found:"), privateLayoutWidget2);
    //combo_label->setFixedSize(combo_label->sizeHint());
    layout->addWidget(combo_label,0,0);
        combo_label->adjustSize();

    check_combo = new TQComboBox(false, privateLayoutWidget2);
   check_combo->insertItem(  i18n( "Ask me" ) );
   check_combo->insertItem(  i18n( "Quarantine file" ) );
   check_combo->insertItem(  i18n( "Just report" ) );
    check_combo->adjustSize();
    //check_combo->setFixedSize(check_combo->size());
    layout->addWidget(check_combo,0,1);


    recursive_box = new TQCheckBox(i18n("&Scan Folders Recursively"), privateLayoutWidget2);
    recursive_box->setMinimumWidth(recursive_box->sizeHint().width());
    recursive_box->setChecked(true);
//     dir_layout2->addSpacing(10);
     layout->addWidget(recursive_box,0,3);
     TQToolTip::add( recursive_box, i18n( "Scan all directories under the specified path." ) );


     TQToolButton* schedule = new TQToolButton( privateLayoutWidget2,"play" );
     schedule->setIconSet( SmallIconSet( "xclock" ) );
    schedule->setTextLabel(i18n( "Schedule" ));
    schedule->setTextPosition(TQToolButton::Right);
    schedule->setUsesTextLabel(true);
     schedule->adjustSize();
     layout->addWidget(schedule,0,4);

    connect( schedule, TQ_SIGNAL(clicked()), tdemain, TQ_SLOT(slotScheduleScan()) );


    TQToolButton* adv_options = new TQToolButton( privateLayoutWidget2,"play" );
    adv_options->setIconSet( SmallIconSet( "configure" ) );
    adv_options->setTextLabel(i18n("Options"));
    adv_options->setTextPosition(TQToolButton::Right);
    adv_options->setUsesTextLabel(true);
    layout->addWidget(adv_options,0,5);
    //adv_options->setFixedSize(adv_options->sizeHint());
    adv_options->adjustSize();

    connect( adv_options, TQ_SIGNAL(clicked()),
        TQ_SLOT(slotAdvOptions()) );

    setup = new CollectionSetup( privateLayoutWidget2, recursive_box->isChecked() );
    layout->addMultiCellWidget(setup, 1, 6,0,6);
    connect( recursive_box, TQ_SIGNAL(toggled(bool)),setup,
        TQ_SLOT(slotRecursiveToggled(bool)) );



    TQHBox* controls = new TQHBox(tabBrowser);
    //controls->setSpacing(5);
    controls->setMargin(2);

    play = new TQToolButton( controls,"play" );
    play->setIconSet( SmallIconSet( "media-playback-start" ) );
    play->setTextLabel(i18n( "Scan" ));
    play->setTextPosition(TQToolButton::Right);
    play->setUsesTextLabel(true);
    play->adjustSize();
    play->setFixedHeight(play->height() - 1);

    stop = new TQToolButton( controls,"stop" );
    stop->setIconSet( SmallIconSet( "media-playback-stop" ) );
    stop->setTextLabel(i18n( "Stop" ));
    stop->setTextPosition(TQToolButton::Right);
    stop->setUsesTextLabel(true);
    stop->adjustSize();
    stop->setFixedHeight(stop->height() - 1);

    m_tabsClose = new TQToolButton( controls,"tab_remove" );
    m_tabsClose->setIconSet( SmallIconSet( "tab_remove" ) );
    m_tabsClose->setTextLabel(i18n( "Close" ));
    m_tabsClose->setTextPosition(TQToolButton::Right);
    m_tabsClose->setUsesTextLabel(true);
    m_tabsClose->adjustSize();
    m_tabsClose->setFixedHeight(m_tabsClose->height() - 1);


    connect( play, TQ_SIGNAL( clicked() ), this,
        TQ_SLOT( slotStartAgain() ) );
    connect( stop, TQ_SIGNAL( clicked() ), this,
        TQ_SLOT( slotStopScanning() ) );
    connect( m_tabsClose, TQ_SIGNAL( clicked() ), this,
        TQ_SLOT( slotRemoveTab() ) );

     controls->adjustSize();
     tabBrowser->setCornerWidget( controls, TopRight );
    ////kdDebug() << "pos: " << controls->pos() << endl;
    //controls->move(controls->pos());


    tabBrowser->addTab(privateLayoutWidget2, i18n( "Launcher"));


    layout->activate();

     connect(tabBrowser, TQ_SIGNAL(currentChanged(TQWidget *)),this,
         TQ_SLOT(slotManageButtons(TQWidget *)) );


     // Register with DCOP
     if ( !kapp->dcopClient()->isRegistered() ) {
         kapp->dcopClient()->registerAs( "dcopklamscan" );
         kapp->dcopClient()->setDefaultObject( objId() );
     }


    if( args->isSet( "scanthis" ) ) {
    slotScan();
    }


}

Klamscan::~Klamscan()
{
}

bool Klamscan::scanGoingOn() {
    // Find any tab in which scanning hasn't finished yet
    for( int i = 1; i < tabBrowser->count(); i++ ) {
        if( dynamic_cast<ScanViewer*>( tabBrowser->page(i) )->scanGoingOn() )
            return true;
    }
    return false;
}


void Klamscan::scan( TQStringList filepattern ) {
    ScanViewer* homepage = new ScanViewer(this, "page");

    connect( homepage, TQ_SIGNAL( scanFinished(TQWidget *) ), this,
        TQ_SLOT( slotManageButtons(TQWidget *) ) );

    connect( homepage, TQ_SIGNAL( scanStartingAgain(TQWidget *) ), this,
        TQ_SLOT( slotManageButtons(TQWidget *) ) );


	tdemain->_tray->setPixmap(KSystemTray::loadIcon("klamav_scanning"));

    TQDate today = TQDate::currentDate();
    TQTime now = TQTime::currentTime();
    TQString suffix = TQString("%1 %2")
        .arg(today.toString("ddd MMMM d yyyy"))
        .arg(now.toString("hh:mm ap"));

    tabBrowser->addTab(homepage,suffix);
    tabBrowser->setCurrentPage(tabBrowser->count() - 1);

    CollectionDB::instance()->insertEvent("Manual Scan",TQString("Commencing Scan"),filepattern.join(" "));

    homepage->slotScan(filepattern, check_combo->currentItem(),setup->recursive(),false);
}


void Klamscan::slotScan()
{
    TQStringList filepattern;

    TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();

    if( args->isSet( "scanthis" ) ) {
        listOfUrlsToScan.clear();
        for( int i = 0; i < args->count(); i++ ) {
            //KMessageBox::information (this,TQString(args->arg(i)));
            filepattern.append(args->arg(i));
            listOfUrlsToScan.prepend(TQString(args->arg(i)));
        }
       prevdir = listOfUrlsToScan.first();

    }else{
            filepattern = setup->pruneSelectedDirs(setup->dirs());
    }

    scan( filepattern );
}


void Klamscan::slotScanFile() {
	KURL::List urls( KFileDialog::getOpenURLs(TQString::null,TQString::null,this) );
	TQStringList filepattern;

	KURL::List::iterator it;
	for( it = urls.begin(); it != urls.end(); ++it ) {
		filepattern.append( (*it).pathOrURL() );
	}

	if( filepattern.count() == 0 )
		return;

	scan( filepattern );
}

void Klamscan::slotScanDir() {
	TQString dir=KFileDialog::getExistingDirectory(TQString::null,this);

	if( dir == TQString::null )
		return;

	scan( TQStringList(dir) );
}


void  Klamscan::slotAdvOptions(){


/*    KlamscanOptions *dialog = new KlamscanOptions( this, "settings");


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

    tdemain->slotConfigKlamav( "Scanning Backend" );


}


void  Klamscan::setDefaults(){

    config = TDEGlobal::config();
    config->setGroup("ScanPaths");

    config->setGroup("Klamscan");

    if ((config->readEntry("NoFilesToExtract")).isEmpty())
        config->writeEntry("NoFilesToExtract","500");

    if ((config->readEntry("RecursionLevel")).isEmpty())
        config->writeEntry("RecursionLevel","8");

//     if ((config->readEntry("MBsToExtract")).isEmpty())
//         config->writeEntry("MBsToExtract","10M");
//
//     if ((config->readEntry("CompressionRatio")).isEmpty())
//         config->writeEntry("CompressionRatio","250");

    if ((config->readEntry("MaxFileSize")).isEmpty())
        config->writeEntry("MaxFileSize","25M");

    if ((config->readEntry("MaxScanSize")).isEmpty())
        config->writeEntry("MaxScanSize","25M");

//     if ((config->readEntry("VirusLimitsExceeded")).isEmpty())
//         config->writeEntry("VirusLimitsExceeded", "Yes");

    if ((config->readEntry("VirusEncrypted")).isEmpty())
        config->writeEntry("VirusEncrypted", "Yes");

    if ((config->readEntry("ScanMail")).isEmpty())
        config->writeEntry("ScanMail", "Yes");

    if ((config->readEntry("ScanPE")).isEmpty())
        config->writeEntry("ScanPE", "Yes");

    if ((config->readEntry("ScanOle")).isEmpty())
        config->writeEntry("ScanOle", "Yes");

    if ((config->readEntry("ScanHTML")).isEmpty())
        config->writeEntry("ScanHTML", "Yes");

    if ((config->readEntry("VirusBroken")).isEmpty())
        config->writeEntry("VirusBroken", "Yes");

    if ((config->readEntry("ExcludeQuarantine")).isEmpty())
        config->writeEntry("ExcludeQuarantine", "Yes");

    if ((config->readEntry("ScanMail")).isEmpty())
        config->writeEntry("ScanMail", "Yes");

    config->sync();

}


void Klamscan::scanURLs(const TQString &urls)
{
    setActiveWindow();
    raise();
    tdemain->tab->setCurrentPage(0);

    TQString tmpurls = urls;
    //urlsToScan = urlsToScan.replace("*"," ");
    urlsToScan = TQStringList::split("*", tmpurls);
    //for ( TQStringList::Iterator it = temp.begin(); it != temp.end(); ++it )
    //        (*it).sprintf("\"%s\"", (*it).latin1());
    //urlsToScan = temp;

    ScanViewer* homepage = new ScanViewer(this, "page");

    connect( homepage, TQ_SIGNAL( scanFinished(TQWidget *) ), this,
        TQ_SLOT( slotManageButtons(TQWidget *) ) );
    connect( homepage, TQ_SIGNAL( scanStartingAgain(TQWidget *) ), this,
        TQ_SLOT( slotManageButtons(TQWidget *) ) );

    TQDate today = TQDate::currentDate();
    TQTime now = TQTime::currentTime();
    TQString suffix = TQString("%1 %2")
        .arg(today.toString("ddd MMMM d yyyy"))
        .arg(now.toString("hh:mm ap"));

    tabBrowser->addTab(homepage,suffix);
    tabBrowser->setCurrentPage(tabBrowser->count() - 1);

    CollectionDB::instance()->insertEvent("Manual Scan",TQString("Commencing Scan"),urlsToScan.join(" "));

    homepage->slotScan(urlsToScan, check_combo->currentItem(),setup->recursive(),true);

}


void  Klamscan::slotStopScanning(){

    tdemain->_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));

    ////kdDebug() << tabBrowser->currentPage()->name() << endl;
    ScanViewer* cur = static_cast<ScanViewer*>(tabBrowser->currentPage());
    cur->slotCancel();


}

void  Klamscan::slotStartAgain(){

    ////kdDebug() << tabBrowser->currentPage()->name() << endl;


    if (tabBrowser->currentPageIndex() != 0){
        ScanViewer* cur = static_cast<ScanViewer*>(tabBrowser->currentPage());
        cur->slotStartAgain();
    }else
        slotScan();

    setup->reset();

    //slotManageButtons(tabBrowser->currentPage());

}

void  Klamscan::slotRemoveTab(){

    tdemain->_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));
    ////kdDebug() << tabBrowser->currentPage()->name() << endl;
    if (tabBrowser->currentPageIndex() != 0){
        slotStopScanning();
        tabBrowser->removePage(tabBrowser->currentPage());
    }
}

void  Klamscan::slotManageButtons(TQWidget * current){

    ScanViewer* cur = static_cast<ScanViewer*>(current);

    if (tabBrowser->currentPageIndex() == 0){
        play->setEnabled(true);
        stop->setEnabled(false);
        m_tabsClose->setEnabled(false);
        return;
    }

    if (cur->scanGoingOn()){
        play->setEnabled(false);
        stop->setEnabled(true);
    }else{
        play->setEnabled(true);
        stop->setEnabled(false);
    }
    m_tabsClose->setEnabled(true);

}

#include "klamscan.moc"
