/***************************************************************************
 *   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 LARGEDATAGRAM_H
#define LARGEDATAGRAM_H

#include <QString>
#include <QObject>
#include <QTimer>
#include <QFile>

#include "globals.h"

/**
	@author Anistratov Oleg <ower@users.sourceforge.net>
*/
class LargeDatagram : public QObject
{
  Q_OBJECT
  private:
    quint8  m_remain; // pokazyvaet skol'ko protsentov ostalos' peredat'
    QString m_filename;
    QFile   m_file;
    bool    m_isFile;
    bool    m_fileInited;
    bool    m_inited;

    QString  m_senderName;
    QString  m_senderCompName;
    quint16  m_programVersion;
    quint16  m_protocolVersion;
    quint64  m_destIP;
    quint64  m_srcIP;
    quint8   m_packetType;
    quint32  m_datagramID;
    quint32  m_channelType;
    quint64  m_totalSize;
    quint32  m_totalFragments;
    quint16  m_fragmentSize;// razmery fragmentov
    quint16  m_lastFragmentSize;// razmer poslednego fragmenta
    /// после того, как будет отправлен запрос на пересылку недостающих фрагментов, необходумо будет знать
    /// после прихода какого фрагмента, в случае необходимости, посылать повторный запрос на пересылку фрагментов
    /// поэтому m_lastFragmentNum наибольший номер среди недостающих фрагментов
    quint32  m_lastFragmentNum;
    quint64  m_firstFragmentTime;
    quint64  m_finalFragmentTime;

    quint64  m_currentSize;
    quint32  m_fragmentsRemain;

    char*    m_fragments; // pokazyvaet kakie fragmenty polucheny, a kakie - net
    char*    m_data;

    /// запрашивает недостающие фрагменты, если ничего не было получено в течение m_requestInterval миллисекунд
    QTimer*  m_requestTimer;
    /// если ничего не было получено в течение m_selfDestroyInterval миллисекунд - происходит уничтожение объекта
    QTimer*  m_selfDestroyTimer;

    quint32  m_requestInterval;
    quint32  m_selfDestroyInterval;

    uint     m_destUid;

  public:
    LargeDatagram(quint64 IP, quint32 ID, QObject* parent = 0);
    ~LargeDatagram();

    const QString & filename() const {return m_filename;}
    quint16               id() const {return m_datagramID;}
    quint64               ip() const {return m_srcIP;}
    bool cmp(quint64 IP, quint32 ID) const {return (IP == m_srcIP && ID == m_datagramID);}
    bool complete() const {return (m_inited && !m_fragmentsRemain);}

    void initDatagram    (const char* dtgrm, quint32 dtgrm_len);
    void addFragment     (const char* dtgrm, quint32 dtgrm_len);
    void addFileFragment (const char* dtgrm, quint32 dtgrm_len);
    void allocateSpace();
    void clear();

    bool fillHeader(QC_DatagramHeader*);

  public slots:
    void slot_fragmentsRequest ();
    void slot_selfDestroy      ();
    void slot_initFile(const QString & filename);

    uint destUid() const {return m_destUid;}

  signals:
    void completed     (LargeDatagram*);
    void wantFragments (char*,  quint32, quint32, quint64);
    void wantDie       (LargeDatagram*);
    void percentsRemain(quint8, quint16, quint64);
    void readyReceive  (quint16, quint64);
};

#endif
