#ifndef FILETRANSDLG_H
#define FILETRANSDLG_H

#include <QItemDelegate>
#include "advwidget.h"
#include "ui_filetrans.h"
#include "s5b.h"

class PsiCon;
class PsiAccount;
class QPixmap;
class FileTransView;
namespace XMPP {
    class FileTransfer;
    class Jid;
    class BoBData;
}
using namespace XMPP;

class FileTransferHandler : public QObject
{
    Q_OBJECT
public:
    enum { ErrReject, ErrTransfer, ErrFile };
    enum { Sending, Receiving };
    FileTransferHandler(PsiAccount *pa, FileTransfer *ft=0);
    ~FileTransferHandler();

    PsiAccount *account() const;
    int mode() const;
    Jid peer() const;
    QString fileName() const;
    qlonglong fileSize() const;
    QString description() const;
    qlonglong offset() const;
    int totalSteps() const;
    bool resumeSupported() const;
    QString saveName() const;
    QString filePath() const;
    QPixmap fileIcon() const;


    void send(const Jid &to, const QString &fname, const QString &desc);
    void accept(const QString &saveName, const QString &fileName, qlonglong offset=0);

signals:
    void accepted();
    void statusMessage(const QString &s);
    void connected();
    void progress(int p, qlonglong sent);
    void error(int, int, const QString &s);

private slots:
    // s5b status
    void s5b_proxyQuery();
    void s5b_proxyResult(bool b);
    void s5b_requesting();
    void s5b_accepted();
    void s5b_tryingHosts(const StreamHostList &hosts);
    void s5b_proxyConnect();
    void s5b_waitingForActivation();

    // ft
    void ft_accepted();
    void ft_connected();
    void ft_readyRead(const QByteArray &);
    void ft_bytesWritten(qint64);
    void ft_error(int);
    void trySend();
    void doFinish();

private:
    class Private;
    Private *d;

    void mapSignals();
};

class FileRequestDlg : public QDialog, public Ui::FileTrans
{
    Q_OBJECT
public:
    FileRequestDlg(const Jid &j, PsiCon *psi, PsiAccount *pa);
    FileRequestDlg(const Jid &j, PsiCon *psi, PsiAccount *pa, const QStringList& files, bool direct = false);
    FileRequestDlg(const QDateTime &ts, FileTransfer *ft, PsiAccount *pa);
    ~FileRequestDlg();

protected:
    void keyPressEvent(QKeyEvent *);

public slots:
    void done(int r);

private slots:
    void updateIdentity(PsiAccount *);
    void updateIdentityVisibility();
    void pa_disconnected();
    void chooseFile();
    void doStart();
    void ft_accepted();
    void ft_statusMessage(const QString &s);
    void ft_connected();
    void ft_error(int, int, const QString &);
    void t_timeout();
    void thumbnailReceived();

private:
    class Private;
    Private *d;

    void blockWidgets();
    void unblockWidgets();
};

class FileTransDlg : public AdvancedWidget<QDialog>
{
    Q_OBJECT
public:
    FileTransDlg(PsiCon *);
    ~FileTransDlg();

    int addItem(const QString &filename, const QString &path, const QPixmap &fileicon, qlonglong size, const QString &peer, bool sending);
    void setProgress(int id, int step, int total, qlonglong sent, int bytesPerSecond, bool updateAll=false);
    void setError(int id, const QString &reason);
    void removeItem(int id);

    void takeTransfer(FileTransferHandler *h, int p, qlonglong sent);
    void killTransfers(PsiAccount *pa);

private slots:
    void clearFinished();
    void ft_progress(int p, qlonglong sent);
    void ft_error(int, int, const QString &s);
    void updateItems();

    void itemCancel(int);
    void itemOpenDest(int);
    void itemClear(int);
    void openFile(QModelIndex);

private:
    class Private;
    Private *d;
};

class FileTransDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    FileTransDelegate(QObject* p);
    void paint(QPainter* mp, const QStyleOptionViewItem& option, const QModelIndex& index) const;
    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;

private:
    FileTransView* ftv;
};

#endif
