/*
 * 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 <qpushbutton.h>
#include <qlayout.h>
#include <kcmdlineargs.h>
#include <kmessagebox.h>
#include <qtooltip.h>
#include <qtoolbutton.h>
#include <dcopclient.h>
#include <qdir.h>
#include <kprogress.h>
#include <dcopref.h>
#include <dcopclient.h>

using namespace KlamAV;

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



/*    scanInProgress = FALSE;    
    multiScan = FALSE;    */
    setDefaults();
    QBoxLayout *top = new QVBoxLayout(this,10,10);


    tabBrowser = new TabWidget(this);
    tabBrowser->setMargin(5);
    top->addWidget(tabBrowser);

    
/*    dblayout->addMultiCellWidget( tabBrowser, 0, 1, 1, 1 );*/
    
    //QGridLayout *layout = new QGridLayout(this, 6, 3, 10, 4);
     QWidget* privateLayoutWidget2 = new QWidget( this, "dblayout" );

    QGridLayout *layout = new QGridLayout(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);
    
    
    


    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();


    QLabel *combo_label = new QLabel(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 QComboBox(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 QCheckBox(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);
     QToolTip::add( recursive_box, i18n( "Scan all directories under the specified path." ) );


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

    connect( schedule, SIGNAL(clicked()),
        SLOT(slotSchedule()) );


    QToolButton* adv_options = new QToolButton( privateLayoutWidget2,"play" );
    adv_options->setIconSet( SmallIconSet( "configure" ) );
    adv_options->setTextLabel(i18n("Options"));
    adv_options->setTextPosition(QToolButton::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)) );

    

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

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

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

    m_tabsClose = new QToolButton( controls,"tab_remove" );
    m_tabsClose->setIconSet( SmallIconSet( "tab_remove" ) );
    m_tabsClose->setTextLabel(i18n( "Close" ));
    m_tabsClose->setTextPosition(QToolButton::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(QWidget *)),this,
         SLOT(slotManageButtons(QWidget *)) );


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



    QDate today = QDate::currentDate();
    QTime now = QTime::currentTime();
    QString suffix = QString("%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;
    
    QStringList filepattern;

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

    }else{    
            filepattern = pruneSelectedDirs();
    }
        //kdDebug() << filepattern << endl;    
    CollectionDB::instance()->insertEvent("Manual Scan",QString("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();*/

    kmain->slotConfigKlamav( "Archive Limits" );
    

}

void  Klamscan::slotSchedule(){

    QStringList 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 = KGlobal::config();
    config->setGroup("ScanPaths");
    
    config->setGroup("Klamscan");

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

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

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


    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 QString &urls)
{
    setActiveWindow();
    raise();
    kmain->tab->setCurrentPage(0);

    QString tmpurls = urls;
    //urlsToScan = urlsToScan.replace("*"," ");
    urlsToScan = QStringList::split("*", tmpurls);
    //for ( QStringList::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(QWidget *) ), this,
        SLOT( slotManageButtons(QWidget *) ) );
    connect( homepage, SIGNAL( scanStartingAgain(QWidget *) ), this,
        SLOT( slotManageButtons(QWidget *) ) );
    
    QDate today = QDate::currentDate();
    QTime now = QTime::currentTime();
    QString suffix = QString("%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",QString("Commencing Scan"),urlsToScan.join(" "));
    
    homepage->slotScan(urlsToScan, check_combo->currentItem(),setup->recursive(),true);

}


void  Klamscan::slotStopScanning(){

    ////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(){

    ////kdDebug() << tabBrowser->currentPage()->name() << endl;
    if (tabBrowser->currentPageIndex() != 0){
        slotStopScanning();
        tabBrowser->removePage(tabBrowser->currentPage());
    }
}

void  Klamscan::slotManageButtons(QWidget * 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);

}

QStringList Klamscan::pruneSelectedDirs(){


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

    QStringList filepattern;
    QStringList listOfUrlsToScan = setup->dirs();
    listOfUrlsToScan.sort();
    QString prev;
    QStringList prevdirs;
    for (QStringList::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 (QStringList::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"
