/***************************************************************************
 *   Copyright (C) 2007 by Anistratov Oleg                                 *
 *   ower@users.sourceforge.net                                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License version 2        *
 *   as published by the Free Software Foundation;                         *
 *                                                                         *
 *   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.                          *
 *                                                                         *
 ***************************************************************************/

#ifndef RECEIVERTHREAD_H
#define RECEIVERTHREAD_H

#include "globals.h"

#include <QThread>
#include <QUdpSocket>
#include <QTimer>
#include <QMutex>
#include <QSocketNotifier>

class LargeDatagram;

/**
	@author Anistratov Oleg <ower@users.sourceforge.net>
*/
class ReceiverThread : public QThread
{
  Q_OBJECT
  private:
    bool              m_opened;
    bool              m_finished;

    LargeDatagram**   m_datagrams;
    quint32           m_datagramsNum;
    quint32           m_datagramsMaxNum;

    char*             m_buffer;
    quint16           m_bufferSize;

    QUdpSocket*       m_socket;
    QSocketNotifier*  m_socketNotifier;
    quint32           m_port;

  private:
    LargeDatagram* findDatagram (quint64 IP, quint32 ID) const;
    void           removeDatagram(LargeDatagram* dtgrm  );

  public:
    ReceiverThread(QObject *parent = 0);
    ~ReceiverThread();

    virtual void   run();
    quint32 getValidID(quint64 IP) const;

    LargeDatagram* addDatagram(quint64 IP, quint32 ID);

  public slots:
    void receiving();
    virtual void changePort(quint16);
    void deleteDatagram(LargeDatagram* dtgrm);
    void slot_acceptDatagram(const QString & filename, quint16, quint64);
    void slot_rejectDatagram(quint16, quint64);
    virtual int readData(char*, uint);


  signals:
    void dataReceived      (char*, quint16);
    void largeDataReceived (LargeDatagram*);
    void wantFragments     (char*, quint32, quint32, quint64);
    void fragmentsRequest  (char* dtgrm, quint32 dtgrm_len);
    /// resend signal from LargeDatagram
    void percentsRemain    (quint8, quint16, quint64);
    void percentsConfirmed (quint8, quint16, quint64);
    void wantReceiveFile   (const QString &, quint16, quint64);
    void readyReceive      (quint16, quint64);
    void receivingAccepted (quint16);
    void receivingRejected (quint16);
    void receivingCancelled(quint16);
    void receivingTimeout  (quint16, quint64);
    void sendingCancelled  (quint16, quint64);
    void openSocketError   (quint16 port);
    void dtgrmFinished     (quint16);
    void portChanged       (quint16);
};

#endif
