/* -*- c++ -*-
*
* previewstreamer.cpp
*
* Copyright (C) 2004 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 "previewstreamer.h"

#include "hostmanager.h"
#include "donkeyhost.h"
#include "donkeyprotocol.h"
#include "fileinfo.h"

#include <kdebug.h>
#include <klocale.h>
#include <kurl.h>
#include <kmimetype.h>
#include <kio/job.h>

#include <time.h>

PreviewStreamerServer::PreviewStreamerServer()
    : GenericHTTPServer("127.0.0.1", 37435)
{
}

GenericHTTPSession* PreviewStreamerServer::buildSession(KExtendedSocket* sock)
{
    return new PreviewStreamer(this, sock);
}



PreviewStreamer::PreviewStreamer(GenericHTTPServer* parent, KExtendedSocket* sock)
    : GenericHTTPSession(parent, sock)
    , m_donkey(0)
    , m_job(0)
    , m_headerSent(false)
{
}

PreviewStreamer::~PreviewStreamer()
{
    delete m_job;
    delete m_donkey;
}

bool PreviewStreamer::processRequest(const QHttpRequestHeader& header, const QByteArray&)
{
    KURL url(header.path());
    QString p(url.path(-1));
    kdDebug() << "Requested path \"" << p << "\"" << endl;
    QStringList path(QStringList::split('/', url.path(-1)));
    if (path.count() != 4 && path.count() != 3)
	return false;
    HostManager* hosts = new HostManager(this, 0, true);
    if (!hosts->validHostName(path[0])) {
	httpError(404, i18n("Unknown host ID"));
	return true;
    }
    m_host = dynamic_cast<DonkeyHost*>(hosts->hostProperties(path[0]));
    if (!m_host) {
	httpError(404, i18n("Not an MLDonkey host"));
	return true;
    }
    bool badAuth = true;
    if (path.count() == 4) {
	if (m_host->password() == path[2])
	    badAuth = false;
    }
    if (path.count() == 3) {
	if (m_host->password().isEmpty())
	    badAuth = false;
    }
    if (m_host->username() != path[1])
	badAuth = true;
    if (badAuth) {
	httpError(404, i18n("Incorrect authentication tokens provided"));
	return true;
    }
    bool ok = false;
    m_id = path[path.count() - 1].toInt(&ok);
    if (!ok) return ok;

    m_donkey = new DonkeyProtocol(true, this);
    connect(m_donkey, SIGNAL(signalConnected()), this, SLOT(donkeyConnected()));
    connect(m_donkey, SIGNAL(signalDisconnected(int)), this, SLOT(donkeyDisconnected(int)));
    connect(m_donkey, SIGNAL(updatedDownloadFiles()), this, SLOT(donkeyMsgReceived()));
    connect(m_donkey, SIGNAL(updatedDownloadedFiles()), this, SLOT(donkeyMsgReceived()));
    m_donkey->setHost(m_host);
    m_donkey->connectToCore();

    return true;
}

void PreviewStreamer::donkeyConnected()
{
    m_ct = 0;
    m_donkey->updateDownloadFiles();
    m_donkey->updateDownloadedFiles();
}

void PreviewStreamer::donkeyDisconnected(int err)
{
    QString msg;
    switch (err) {
    case ProtocolInterface::AuthenticationError:
	msg = i18n("Incorrect authentication tokens provided");
	break;
    case ProtocolInterface::NoError:
	deleteLater();
	return;
    case ProtocolInterface::ConnectionRefusedError:
	msg = i18n("Core is not running");
	break;
    default:
	msg = i18n("Problem communicating with core");
	break;
    }
    httpError(404, msg);
}

void PreviewStreamer::donkeyMsgReceived()
{
    m_ct++;
    if (m_ct < 2)
	return;
    m_file = m_donkey->findDownloadFileNo(m_id);
    if (!m_file) m_file = m_donkey->findDownloadedFileNo(m_id);
    if (!m_file) {
	httpError(404);
	return;
    }
    KURL path;
    path.setProtocol("http");
    path.setUser(m_host->username());
    path.setPass(m_host->password());
    path.setHost(m_host->address());
    path.setPort(m_host->httpPort());
    path.setPath("/preview_download");
    path.setQuery(QString("?q=%1").arg(m_file->fileNo()));
    m_streamed = 0;
    m_ct = time(0);
    m_job = KIO::get(path, false, false);
    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)), this, SLOT(dataArrived(KIO::Job*, const QByteArray&)));
    connect(m_job, SIGNAL(result(KIO::Job*)), this, SLOT(ioResult(KIO::Job*)));
}

void PreviewStreamer::dataArrived(KIO::Job*, const QByteArray& data)
{
    if (!m_headerSent) {
	KMimeType::Ptr mimeType = KMimeType::findByPath(m_file->fileName());
	sendResponseHeader(mimeType->property("Name").toString(), m_file->fileSize());
	m_headerSent = true;
    }
    m_streamed += data.size();
    sendData(data);
    if (time(0) > m_ct + 3) {
	m_ct = time(0);
    }
}

void PreviewStreamer::ioResult(KIO::Job*)
{
    // if (job->error())
    endRequest();
}








#include "previewstreamer.moc"
