/*
 * 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 <tqpushbutton.h>
#include <tqlayout.h>
#include <tdecmdlineargs.h>
#include <tdemessagebox.h>
#include <tqtooltip.h>
#include <tqtoolbutton.h>
#include <dcopclient.h>
#include <tqdir.h>
#include <kprogress.h>
#include <dcopref.h>
#include <dcopclient.h>

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);
    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, SIGNAL(clicked()),
        SLOT(slotSchedule()) );


    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, SIGNAL(clicked()),
        SLOT(slotAdvOptions()) );

    setup = new CollectionSetup( privateLayoutWidget2, recursive_box->isChecked() );
    layout->addMultiCellWidget(setup, 1, 6,0,6);
    connect( recursive_box, SIGNAL(toggled(bool)),setup,
        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, SIGNAL( clicked() ), this,
        SLOT( slotStartAgain() ) );
    connect( stop, SIGNAL( clicked() ), this,
        SLOT( slotStopScanning() ) );
    connect( m_tabsClose, SIGNAL( clicked() ), this,
        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, SIGNAL(currentChanged(TQWidget *)),this,
         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()
{
}





void Klamscan::slotScan()
{


    ScanViewer* homepage = new ScanViewer(this, "page");
    
    connect( homepage, SIGNAL( scanFinished(TQWidget *) ), this,
        SLOT( slotManageButtons(TQWidget *) ) );
    
    connect( homepage, SIGNAL( scanStartingAgain(TQWidget *) ), this,
        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);
    //return;
    
    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 = pruneSelectedDirs();
    }
        //kdDebug() << filepattern << endl;    
    CollectionDB::instance()->insertEvent("Manual Scan",TQString("Commencing Scan"),filepattern.join(" "));

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



void  Klamscan::slotAdvOptions(){


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

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

    tdemain->slotConfigKlamav( "Archive Limits" );
    

}

void  Klamscan::slotSchedule(){

    TQStringList filepattern = pruneSelectedDirs();


    if (filepattern.isEmpty()){
        KMessageBox::error(this, i18n( "Please select something to scan!") );
        return;
    }

    Schedule *dialog = new Schedule( this, filepattern, "settings");
    dialog->show();
    dialog->raise();
    dialog->setActiveWindow();
    

}


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, SIGNAL( scanFinished(TQWidget *) ), this,
        SLOT( slotManageButtons(TQWidget *) ) );
    connect( homepage, SIGNAL( scanStartingAgain(TQWidget *) ), this,
        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();

    //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);

}

TQStringList Klamscan::pruneSelectedDirs(){


    //This gets rid of redundant sub-directories from the list of dirs to be scanned.

    TQStringList filepattern;
    TQStringList listOfUrlsToScan = setup->dirs();
    listOfUrlsToScan.sort();
    TQString prev;
    TQStringList prevdirs;
    for (TQStringList::Iterator it = listOfUrlsToScan.begin(); it != listOfUrlsToScan.end(); it++ ){
        //kdDebug() << "dir: " << (*it) << endl;
        (*it) = (*it).stripWhiteSpace() + "/";
        if (prevdirs.isEmpty()){
            //kdDebug() << (*it) << endl;
            filepattern.append(*it);
            prevdirs.append((*it));
        }else{
            filepattern.append(*it);
            bool shouldappend = true;
            for (TQStringList::Iterator it2 = prevdirs.begin(); it2 != prevdirs.end(); it2++ ){
                if ((*it).contains(*it2)){
                    //kdDebug() << (*it) << endl;
                    filepattern.remove((*it));
                    shouldappend = false;
                    break;
                }
            }
            if (shouldappend)
               prevdirs.append((*it));
        }
    }


       
        return filepattern;

}


#include "klamscan.moc"