/* -*- c++ -*-
 *
 * search.cpp
 *
 * Copyright (C) 2003-2004 Petter Stokke <ummo@hellokitty.com>
 * Copyright (C) 2003-2004 Sebastian Sauer <mail@dipe.org>
 * Copyright (C) 2006      Christian Muehlhaeuser <chris@chris.de>
 *
 * 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., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include <qlabel.h>
#include <qvbox.h>
#include <qgroupbox.h>
#include <qscrollview.h>
#include <qsplitter.h>
#include <qcheckbox.h>
#include <qlayout.h>
#include <qclipboard.h>
#include <qregexp.h>

#include <kdebug.h>
#include <klocale.h>
#include <kconfig.h>
#include <klineedit.h>
#include <kpushbutton.h>
#include <kcombobox.h>
#include <kaction.h>
#include <kmimetype.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <ktabwidget.h>

#include "kmldonkey.h"
#include "search.h"
#include "prefs.h"

#include <searchquery.h>
#include <searchinfo.h>
#include <network.h>

#include <kdeversion.h>


SearchPage::SearchPage( QWidget *parent )
    : QVBox( parent, "searchPage" )
    , KMLDonkeyPage()
    , ClipboardHelper()
{
    splitter = new QSplitter( this );

    searchcore = new SearchCore( splitter, this );
    splitter->setResizeMode( searchcore, QSplitter::KeepSize );

    QVBox* rightBox = new QVBox( splitter );
    ed2kBox = new QHBox( rightBox );
    ed2kBox->setMargin( 6 );
    ed2kBox->setSpacing( 6 );
    QLabel* ed2kLabel = new QLabel( i18n( "Enter &URL to download:" ), ed2kBox );
    ed2kEntry = new KLineEdit( ed2kBox, "ed2kEntry" );
    ed2kLabel->setBuddy( ed2kEntry );
    connect( ed2kEntry, SIGNAL( returnPressed() ), SLOT( submitED2K() ) );

    resultTabs = new KTabWidget( rightBox );
    resultTabs->setHoverCloseButton( true );
    resultTabs->setTabReorderingEnabled( true );
    connect( resultTabs, SIGNAL( closeRequest( QWidget* ) ), this, SLOT( closeSearch( QWidget* ) ) );
    connect( resultTabs, SIGNAL( currentChanged( QWidget* ) ), this, SLOT( currentTabChanged( QWidget* ) ) );

    connect( KMLDonkey::App->donkey, SIGNAL( searchUpdated( int,const ResultInfo* ) ), this, SLOT( searchUpdated( int, const ResultInfo* ) ) );
}


void SearchPage::handleGenericAction( const QString& action )
{
    if (action == "copy_url") copySearchToClipboard(URL);
    else if (action == "copy_html") copySearchToClipboard(HTML);
    else if (action == "copy_hash") copySearchToClipboard(Hash);
    else if (action == "search_download") actionDownload();
    else if (action == "search_force_download") actionForceDownload();
    else if (action == "search_download_as") actionDownloadAs();
}


void SearchPage::deactivatePageActions()
{
    searchcore->deactivateActions();
}


QStringList SearchPage::supportedGenericActions()
{
    QStringList actions;
    SearchResult *sr = (SearchResult*)resultTabs->currentPage();
    if (sr && sr->resultView->hasFocus() && !sr->resultView->selectedItems().isEmpty()) {
        actions.append("copy_url");
        actions.append("copy_html");
        actions.append("copy_hash");
        actions.append("search_download");
        actions.append("search_force_download");
        actions.append("search_download_as");
    }

    if( KMLDonkey::App->donkey->isConnected() )
        searchcore->activateActions();

    return actions;
}


void SearchPage::plugGenericActions(QObject* object, const char* slot)
{
    connect(this, SIGNAL(genericActionsChanged(KMLDonkeyPage*)), object, slot);
}


void SearchPage::pleaseUpdateActions()
{
    emit genericActionsChanged(static_cast<KMLDonkeyPage*>(this));
}


void SearchPage::setupActions( KActionCollection* actionCollection )
{
    (void)new KAction( i18n( "Activate Search Page" ), 0, 0, this, SLOT( actionActivatePage() ),
                       actionCollection, "activate_page_search" );
}


void SearchPage::configurePrefsDialog(KMLDonkeyPreferences* prefs)
{
    prefs->searchPage->activateNewTabsCheckbox->setChecked(activateNewTabs);
    prefs->searchPage->closeTabsOnDisconnectCheckbox->setChecked(closeTabsOnDisconnect);
    prefs->searchPage->showNumbersOnTabsCheckbox->setChecked(showNumbersOnTabs);
    prefs->searchPage->showSubmitURLCheckbox->setChecked(showSubmitURL);
}


void SearchPage::applyPreferences(KMLDonkeyPreferences* prefs)
{
    activateNewTabs = prefs->searchPage->activateNewTabsCheckbox->isChecked();
    closeTabsOnDisconnect = prefs->searchPage->closeTabsOnDisconnectCheckbox->isChecked();
    showNumbersOnTabs = prefs->searchPage->showNumbersOnTabsCheckbox->isChecked();

    if (showSubmitURL != prefs->searchPage->showSubmitURLCheckbox->isChecked()) {
        showSubmitURL = prefs->searchPage->showSubmitURLCheckbox->isChecked();
        if (showSubmitURL)
            ed2kBox->show();
        else
            ed2kBox->hide();
        ed2kBox->updateGeometry();
    }

    QIntDictIterator<SearchResult> it( Results );
    for ( ; it.current(); ++it ) {
        it.current()->setListFont(KMLDonkey::App->listFont);
        resultTabs->setTabLabel(it.current(), getTabLabel(it.current()));
    }
}


QString SearchPage::getTabLabel(SearchResult *tab)
{
    if (! showNumbersOnTabs) return tab->getTabLabel();
    return tab->getTabLabel() + " (" + QString::number(tab->resultView->childCount()) + ")";
}


void SearchPage::saveState(KConfig* conf)
{
    conf->setGroup("Search");
    conf->writeEntry("Splitter", splitter->sizes());
    conf->writeEntry("activateNewTabs", activateNewTabs);
    conf->writeEntry("closeTabsOnDisconnect", closeTabsOnDisconnect);
    conf->writeEntry("showNumbersOnTabs", showNumbersOnTabs);
    conf->writeEntry("showSubmitURL", showSubmitURL);

    searchcore->saveState(conf);
}


void SearchPage::restoreState(KConfig* conf)
{
    conf->setGroup("Search");
    splitter->setSizes(conf->readIntListEntry("Splitter"));
    activateNewTabs = conf->readBoolEntry("activateNewTabs", true);
    closeTabsOnDisconnect = conf->readBoolEntry("closeTabsOnDisconnect", true);
    showNumbersOnTabs = conf->readBoolEntry("showNumbersOnTabs", true);

    showSubmitURL = conf->readBoolEntry("showSubmitURL", true);
    if (showSubmitURL)
        ed2kBox->show();
    else
        ed2kBox->hide();
    ed2kBox->updateGeometry();

    searchcore->restoreState(conf);
}


void SearchPage::clear()
{
    searchcore->clear();
    searchcore->deactivateActions();
    if(closeTabsOnDisconnect) closeAllSearches();
}


void SearchPage::submitED2K()
{
    KMLDonkey::App->donkey->submitURL(ed2kEntry->text());
    ed2kEntry->clear();
}


void SearchPage::searchUpdated( int searchnum, const ResultInfo* searchinfo )
{
    SearchResult *sr = Results[searchnum];
    if ( !sr ) return;

    sr->addItem( searchinfo );
    resultTabs->setTabLabel( sr, getTabLabel( sr ) );
}


void SearchPage::stopSearch( int id )
{
    if ( KMLDonkey::App->donkey->isConnected() )
        KMLDonkey::App->donkey->stopSearch( id );

    Results.remove( id );
}


SearchResult* SearchPage::addSearchResult(int searchNum, SearchQuery* query, const QString& tablabel)
{
    SearchResult *sr = new SearchResult(resultTabs, tablabel, searchNum);
    connect(sr->resultView, SIGNAL(selectionChanged()), SLOT(pleaseUpdateActions()));
    connect(sr->resultView, SIGNAL(gotFocus()), SLOT(pleaseUpdateActions()));
    Results.replace(searchNum, sr);
    sr->setListFont(KMLDonkey::App->listFont);
    sr->setSearchLabel(query->getQuerystring());
    resultTabs->addTab(sr, KGlobal::iconLoader()->loadIconSet("fileclose", KIcon::Small), getTabLabel(sr));
    if (activateNewTabs) resultTabs->setCurrentPage(resultTabs->count()-1);
    return sr;
}


void SearchPage::stopAllSearches()
{
    if (! KMLDonkey::App->donkey->isConnected()) return;
    QIntDictIterator<SearchResult> it( Results );
    for ( ; it.current(); ++it )
        KMLDonkey::App->donkey->stopSearch( it.currentKey() );
}


void SearchPage::closeSearch(QWidget* widget)
{
    int id = static_cast<SearchResult*>(widget)->searchNo();
    stopSearch(id);
    delete widget;
    pleaseUpdateActions();
}


void SearchPage::currentTabChanged( QWidget *w )
{
}


void SearchPage::closeAllSearches()
{
    while (resultTabs->count()) {
        int id = static_cast<SearchResult*>( resultTabs->currentPage() )->searchNo();
        stopSearch(id);
        delete resultTabs->currentPage();
    }
    pleaseUpdateActions();
}


void SearchPage::actionDownload()
{
    SearchResult *sr = (SearchResult*)resultTabs->currentPage();
    if (sr) sr->DownloadSelectedItems(false, false);
}

void SearchPage::actionForceDownload()
{
    SearchResult *sr = (SearchResult*)resultTabs->currentPage();
    if (sr) sr->DownloadSelectedItems(true, false);
}


void SearchPage::actionDownloadAs()
{
    SearchResult *sr = (SearchResult*)resultTabs->currentPage();
    if (sr) sr->DownloadSelectedItems(false, true);
}


void SearchPage::copySearchToClipboard(ClipFormat format)
{
    SearchResult *sr = (SearchResult*)resultTabs->currentPage();
    if (! sr) return;
    QStringList sl;
    QPtrList<QListViewItem> list = sr->resultView->selectedItems();
    SearchResultItem *item;
    for (item = (SearchResultItem*)list.first(); item; item = (SearchResultItem*)list.next()) {
        sl.append( item->getName() ); // filename
        sl.append( item->getEd2kHash() ); // filehash
        sl.append( QString::number((long)item->getSize()) ); // filesize
    }
    copyToClipboard(sl, format);
}


void SearchPage::actionActivatePage()
{
    KMLDonkey::App->activatePage( this );
}

#include "search.moc"
