/* -*- c++ -*-
 *
 * sharepage.cpp
 *
 * Copyright (C) 2003 Petter Stokke <ummo@hellokitty.com>
 *
 * 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 <kdebug.h>
#include <klocale.h>
#include <kconfig.h>
#include <kaction.h>
#include <knuminput.h>
#include <kmimetype.h>

#include <qintdict.h>
#include <qpopupmenu.h>
#include <qclipboard.h>
#include <qregexp.h>
#include <qtimer.h>
#include <qcheckbox.h>

#include "infolist.h"
#include "prefs.h"
#include "kmldonkey.h"
#include "shareddirs.h"

#include "network.h"
#include "shareinfo.h"
#include "clientinfo.h"

#include "sharepage.h"
#include "sharepage.moc"

// SharedFile

QString SharedFile::xtext(int col) const
{
    ShareInfo* it = KMLDonkey::App->donkey->findShareNo(fileno);
    if (!it) {
        if (!col) return i18n("Unknown share");
        return i18n("signifies absence of data in list columns", "-");
    }
    switch (col) {
    case 0: // name
        return it->shareName();
    case 1: // network
        return KMLDonkey::App->donkey->findNetworkNo(it->shareNetwork())->networkName();
    case 2: // requests
        return KGlobal::locale()->formatNumber(it->shareRequests(), 0);
    case 3: // bytes
        return humanReadableSize(it->shareUploaded());
    case 4: // File Type
        return KMimeType::findByURL( KURL( "file:/" + it->shareName() ), 0, false, true)->comment();
    default:
        return "ERROR!";
    }
}

double SharedFile::numeric(int col) const
{
    ShareInfo* it = KMLDonkey::App->donkey->findShareNo(fileno);
    if (!it) return 0.0;
    switch (col) {
    case 2:
        return (double)it->shareRequests();
    case 3:
        return (double)it->shareUploaded();
    default:
        return 0.0;
    }
}

bool SharedFile::isNumeric(int col) const
{
    switch (col) {
    case 2:
    case 3:
        return true;
    default:
        return false;
    }
}

// UploadersFile

QString UploadersFile::xtext(int col) const
{
    ClientInfo *ci = KMLDonkey::App->donkey->findClientNo(fileno);
    if (ci)
        switch (col) {
            case 0: return ci->clientUpload();
            case 1: return ci->clientName();
            case 2: return humanReadableSize(ci->clientDownloaded());
            case 3: return humanReadableSize(ci->clientUploaded());
            case 4:
                switch (ci->clientState()) {
                case ClientInfo::NotConnected:
                case ClientInfo::NotConnected2: return i18n("not connected to host", "Not connected");
                case ClientInfo::Connecting: return i18n("connecting to host", "Connecting");
                case ClientInfo::Initiating: return i18n("initiating connection to host", "Initiating");
                case ClientInfo::Downloading: return i18n("downloading from host", "Downloading");
                case ClientInfo::Connected:
                case ClientInfo::Connected3: return i18n("connected to host", "Connected");
                case ClientInfo::Connected2: return i18n("we're at this position in client's queue", "Queued: %1")
                                                    .arg(KGlobal::locale()->formatNumber(ci->clientQueuePosition(), 0));
                case ClientInfo::NewHost: return i18n("new host added to list", "New host");
                case ClientInfo::Removed: return i18n("host has been removed", "Removed");
                case ClientInfo::Blacklisted: return i18n("host is blacklisted", "Blacklisted");
                default: return i18n("unknown host state (unknown ID code)", "Unknown (%1)").arg(ci->clientState());
                }
            case 5: return KMLDonkey::App->donkey->findNetworkNo(ci->clientNetwork())->networkName();
            case 6: return QString::number(ci->clientRating());
            case 7: return humanReadableTime((time_t)ci->clientConnectTime(), true);
            case 8: return ci->clientSoftware() + " " + ci->clientEmuleMod();
            case 9: return KMimeType::findByURL( KURL( "file:/" + ci->clientUpload() ), 0, false, true)->comment();
            default: break;
        }

    return "-";
}

double UploadersFile::numeric(int col) const
{
    ClientInfo *ci = KMLDonkey::App->donkey->findClientNo(fileno);
    if (ci)
        switch (col) {
            case 2: return (double)ci->clientDownloaded();
            case 3: return (double)ci->clientUploaded();
            case 6: return ci->clientRating();
            default: break;
       }
    return 0.0;
}

bool UploadersFile::isNumeric(int col) const
{
    switch (col) {
        case 2:
        case 3:
        case 6:
            return true;
        default: break;
    }
    return false;
}

// SharePage

SharePage::SharePage(QWidget* parent)
    : QVBox(parent, "sharePage")
    , KMLDonkeyPage()
    , ClipboardHelper()
{
    shareList.setAutoDelete(true);
    uploadList.setAutoDelete(true);

    refreshTimer = new QTimer(this, "refreshTimer");

    uploadSplitter = new QSplitter(this, "uploadSplitter");
    uploadSplitter->setOrientation(QSplitter::Vertical);

    uploadView = new InfoList(uploadSplitter, "uploadView", true);
    uploadView->addColumn( i18n( "File name" ) );
    uploadView->addColumn( i18n( "Network" ) );
    uploadView->addColumn( i18n( "Requests" ) );
    uploadView->addColumn( i18n( "Bytes" ) );
    uploadView->addColumn( i18n( "File type" ) );

    uploadersView = new InfoList(uploadSplitter, "uploadersView", true);
    uploadersView->addColumn( i18n( "File name" ) );
    uploadersView->addColumn( i18n( "Name" ) );
    uploadersView->addColumn( i18n( "Downloaded" ) );
    uploadersView->addColumn( i18n( "Uploaded" ) );
    uploadersView->addColumn( i18n( "Status" ) );
    uploadersView->addColumn( i18n( "Network" ) );
    uploadersView->addColumn( i18n( "Rating" ) );
    uploadersView->addColumn( i18n( "Time" ) );
    uploadersView->addColumn( i18n( "Software" ) );
    uploadersView->addColumn( i18n( "File type" ) );

    connect(uploadView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
	    this, SLOT(contextUpload(KListView*, QListViewItem*, const QPoint&)));
    connect(uploadView, SIGNAL(selectionChanged()), SLOT(clearUploadersSelection()));

    connect(uploadersView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
	    this, SLOT(contextUploaders(KListView*, QListViewItem*, const QPoint&)));
    connect(uploadersView, SIGNAL(selectionChanged()), SLOT(clearUploadSelection()));

    connect(KMLDonkey::App->donkey, SIGNAL(shareUpdated(int)), this, SLOT(shareUpdated(int)));
    connect(KMLDonkey::App->donkey, SIGNAL(shareRemoved(int)), this, SLOT(shareRemoved(int)));

    connect(KMLDonkey::App->donkey, SIGNAL(uploadRemoved(int)), this, SLOT(actionRemoveUploader(int)));
    connect(KMLDonkey::App->donkey, SIGNAL(uploadUpdated(int)), this, SLOT(actionUpdateUploader(int)));

    connect(KMLDonkey::App->donkey, SIGNAL(signalConnected()), this, SLOT(actionRefreshUploaders()));

    connect(refreshTimer, SIGNAL(timeout()), SLOT(refreshLists()));
}

void SharePage::handleGenericAction(const QString& action)
{
    if (uploadView->hasFocus()) {
	if (action == "copy_url") copyFileToClipboard(URL);
	else if (action == "copy_html") copyFileToClipboard(HTML);
	else if (action == "copy_hash") copyFileToClipboard(Hash);
    }

    else if (uploadersView->hasFocus()) {
    }
}

void SharePage::showEvent(QShowEvent*)
{
    if (KMLDonkey::App->donkey->isConnected() && ! autoUpdate) {
        actionRefreshShared();
        actionRefreshUploaders();
    }
}

void SharePage::deactivatePageActions()
{
    enableActionList(uploadActions, false);
    enableActionList(uploadersActions, false);
}

QStringList SharePage::supportedGenericActions()
{
    QStringList actions;
    QPtrList<QListViewItem> ul = uploadView->selectedItems();
    QPtrList<QListViewItem> sl = uploadersView->selectedItems();

    if (!ul.isEmpty()) {
	enableActionList(uploadActions, true);
	actions.append("copy_url");
	actions.append("copy_html");
	actions.append("copy_hash");
    }
    else enableActionList(uploadActions, false);

    if (!sl.isEmpty()) {
	enableActionList(uploadersActions, true);
    }
    else enableActionList(uploadersActions, false);

    return actions;
}

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

void SharePage::clearUploadSelection()
{
    uploadView->blockSignals(true);
    uploadView->clearSelection();
    uploadView->blockSignals(false);
    emit genericActionsChanged(static_cast<KMLDonkeyPage*>(this));
}

void SharePage::clearUploadersSelection()
{
    uploadersView->blockSignals(true);
    uploadersView->clearSelection();
    uploadersView->blockSignals(false);
    emit genericActionsChanged(static_cast<KMLDonkeyPage*>(this));
}

void SharePage::setupActions(KActionCollection* actionCollection)
{
    refreshShared = new KAction(i18n("&Refresh Shared File List"), "reload", 0, this, SLOT(actionRefreshShared()),
				actionCollection, "upload_refresh");
    refreshUploaders = new KAction(i18n("Refresh U&ploaders List"), "reload", 0, this, SLOT(actionRefreshUploaders()),
				   actionCollection, "uploaders_refresh");

    KMLDonkey::App->addCoreAction( new KAction(i18n("&Shared Folders..."), "fileimport", 0, this, SLOT(actionSharedDirs()),
		                   actionCollection, "shared_dirs") );

    (void)new KAction(i18n("Activate Uploads Page"), 0, 0, this, SLOT(actionActivatePage()),
		      actionCollection, "activate_page_uploads");

    deactivatePageActions();
}

void SharePage::clear()
{
    shareList.clear();
    uploadList.clear();
    uploadView->clear();
    uploadersView->clear();
}

void SharePage::configurePrefsDialog(KMLDonkeyPreferences* prefs)
{
    prefs->listsPage->autoUpdateCheckbox->setChecked(autoUpdate);
    prefs->listsPage->updateFrequencyEntry->setValue(updateFrequency);
}

void SharePage::applyPreferences(KMLDonkeyPreferences* prefs)
{
    if (prefs) {
	autoUpdate = prefs->listsPage->autoUpdateCheckbox->isChecked();
	updateFrequency = prefs->listsPage->updateFrequencyEntry->value();
    }

    updateTimer();

    if (KMLDonkey::App->listFont !=  uploadView->font())
        uploadView->setFont(KMLDonkey::App->listFont);
    if (KMLDonkey::App->listFont !=  uploadersView->font())
        uploadersView->setFont(KMLDonkey::App->listFont);
}

void SharePage::restoreState(KConfig* conf)
{
    conf->setGroup("Options");
    autoUpdate = conf->readBoolEntry("AutoUpdateShareLists", false);
    updateFrequency = conf->readNumEntry("ShareListUpdateFrequency", 10);

    conf->setGroup("Splitters");
    uploadSplitter->setSizes(conf->readIntListEntry("UploadSplitter"));

    uploadView->initialise();
    uploadersView->initialise();

    applyPreferences();
}

void SharePage::saveState(KConfig* conf)
{
    conf->setGroup("Options");
    conf->writeEntry("AutoUpdateShareLists", autoUpdate);
    conf->writeEntry("ShareListUpdateFrequency", updateFrequency);

    conf->setGroup("Splitters");
    conf->writeEntry("UploadSplitter", uploadSplitter->sizes());

    uploadView->saveLayout();
    uploadersView->saveLayout();
}

void SharePage::contextUpload(KListView*,QListViewItem*,const QPoint& pt)
{
    QPopupMenu *pop = (QPopupMenu*)(KMLDonkey::App->factory())->container("upload_actions", KMLDonkey::App);
    if (!pop)
	KMLDonkey::App->showBadInstallDialog();
    else
	pop->popup(pt);
}

void SharePage::contextUploaders(KListView*,QListViewItem*,const QPoint& pt)
{
    QPopupMenu *pop = (QPopupMenu*)(KMLDonkey::App->factory())->container("uploaders_actions", KMLDonkey::App);
    if (!pop)
	KMLDonkey::App->showBadInstallDialog();
    else
	pop->popup(pt);
}

void SharePage::actionRefreshShared()
{
    KMLDonkey::App->donkey->refreshShared();
}

void SharePage::actionSharedDirs()
{
    if (! KMLDonkey::App->donkey->isConnected()) return;
    SharedDirsDialog *dlg = new SharedDirsDialog(this, "SharedDirsDialog");
    if (dlg) dlg->show();
}

void SharePage::shareUpdated(int share)
{
    ShareInfo* si = KMLDonkey::App->donkey->findShareNo(share);
    if (!si) return;

    SharedFile* df = shareList[share];
    if (df) {
        df->refresh();
        return;
    }
    df = new SharedFile(uploadView, share);
    shareList.insert(share, df);
}

void SharePage::shareRemoved(int share)
{
    shareList.remove(share);
}

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

void SharePage::copyFileToClipboard(ClipFormat format)
{
    QStringList l;
    QPtrList<QListViewItem> list = uploadView->selectedItems();
    SharedFile* it;
    for (it = (SharedFile*)list.first(); it; it = (SharedFile*)list.next()) {
	const ShareInfo* fi = KMLDonkey::App->donkey->findShareNo(it->fileNo());
	if (!fi) continue;
        l.append(fi->shareName());
        l.append(fi->shareUid("ed2k"));
        l.append(QString::number((long int)fi->shareSize()));
    }
    copyToClipboard(l, format);
}

void SharePage::actionRefreshUploaders()
{
    KMLDonkey::App->donkey->updateUploaders();
}

void SharePage::refreshLists()
{
    actionRefreshShared();
    actionRefreshUploaders();
}

void SharePage::updateTimer()
{
    refreshShared->setEnabled(!autoUpdate);
    refreshUploaders->setEnabled(!autoUpdate);
    if (!autoUpdate) {
	if (refreshTimer->isActive()) refreshTimer->stop();
	return;
    }

    if (refreshTimer->isActive()) {
	if (updateFrequency * 1000 != activeFrequency) {
	    activeFrequency = updateFrequency * 1000;
	    refreshTimer->changeInterval(activeFrequency);
	}
    } else {
	activeFrequency = updateFrequency * 1000;
	refreshTimer->start(activeFrequency);
    }
}

void SharePage::actionUpdateUploader(int clientnum)
{
    // kdDebug() << "SharePage::actionUpdateUploader" << clientnum << endl;
    ClientInfo *ci = KMLDonkey::App->donkey->findClientNo(clientnum);
    if (! ci) {
        kdDebug() << "SharePage::actionUpdateUploader ClientInfo not ready." << endl;
        return;
    }
    UploadersFile *uf = uploadList[clientnum];
    if (! uf) {
        uf = new UploadersFile(uploadersView, clientnum);
        uploadList.insert(clientnum, uf);
    }
    uf->refresh();
}

void SharePage::actionRemoveUploader(int clientnum)
{
    uploadList.remove(clientnum);
}

