/***************************************************************************
 *   Copyright (C) 2007 by Anistratov Oleg                                 *
 *   ower86@gmail.com                                                      *
 *                                                                         *
 *   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 PROTOCOLVERSION3_H
#define PROTOCOLVERSION3_H

#include <abstractprotocol.h>

/**
        @author Anistratov Oleg <ower86@gmail.com>
*/
class ProtocolVersion3 : public AbstractProtocol
{
  private:
    static const char* m_programId;

  public:
    ProtocolVersion3();
    ~ProtocolVersion3();

    // Protocol information functions
    uint  protocolVersion() const {return 3;}
    uint  protocolLen    () const {return 69;}
    const char* programId() const {return m_programId;}
    uint optionsLen() const {return 0;}

    // NOTE size of char* buf in following functions must be at least AbstractChatCore::protocolLen() bytes

    QString programId       (const char* buf){return QString::fromAscii(buf, 18);} // 18 bytes

    // Only for server mode
    uint    packetSize      (const char* buf){return str2US (buf + 16);} // 2

    uint    programVersion  (const char* buf){return str2US (buf + 18);} // 2
    uint    protocolVersion (const char* buf){return str2US (buf + 20);} // 2
    quint64 destIp          (const char* buf){return str2ULL(buf + 22);} // 8
    quint64 srcIp           (const char* buf){return str2ULL(buf + 30);} // 8
    uint    packetType      (const char* buf){return       *(buf + 38);} // 1
    uint    packetId        (const char* buf){return str2US (buf + 39);} // 2
    uint    fragmentSize    (const char* buf){return str2US (buf + 41);} // 2
    uint    packetNum       (const char* buf){return str2UL (buf + 43);} // 4
    quint64 time            (const char* buf){return str2ULL(buf + 47);} // 8
    uint    channelType     (const char* buf){return str2UL (buf + 55);} // 4
    uint    compNameLen     (const char* buf){return       *(buf + 59);} // 1
    uint    userNameLen     (const char* buf){return       *(buf + 60);} // 1
    uint    messageLen      (const char* buf){return str2UL (buf + 61);} // 4
    uint    parametrsLen    (const char* buf){return str2UL (buf + 65);} // 4
    uint    optionsLen      (const char* /*buf*/){return 0;}
    bool    compressed      (const char* /*buf*/){return false;}

    QString compName        (const char* buf, uint sz);
    QString userName        (const char* buf, uint sz);
    QString message         (const char* buf, uint sz);
    QByteArray parametrs    (const char* buf, uint sz);

    void setProgramId      (char* buf){strncpy(buf, programId(), 18);}

    // Only for server mode
    void setPacketSize     (char* buf, uint sz){catUS2str(buf + 16, sz);} // 2

    void setProgramVersion (char* buf){catUS2str(buf + 18, Globals::VersionID);}
    void setProtocolVersion(char* buf){catUS2str(buf + 20, protocolVersion());}

    void setDestIp         (char* buf, quint64 ip){catULL2str(buf + 22, ip);} // 8
    void setSrcIp          (char* buf, quint64 ip){catULL2str(buf + 30, ip);} // 8
    void setPacketType     (char* buf, uint  type){(buf[38] = type);} // 1
    void setPacketId       (char* buf, uint    id){catUS2str(buf + 39, id);} // 2
    void setFragmentSize   (char* buf, uint    sz){catUS2str(buf + 41, sz);} // 2
    void setPacketNum      (char* buf, quint32 nm){catUL2str (buf + 43, nm);} // 4
    void setTime           (char* buf, quint64 tm){catULL2str(buf + 47, tm);} // 8
    void setChannelType    (char* buf, quint32 id){catUL2str (buf + 55, id);} // 4
    void setCompNameLen    (char* buf, uint    sz){buf[59] = sz;} // 1
    void setUserNameLen    (char* buf, uint    sz){buf[60] = sz;} // 1
    void setMessageLen     (char* buf, quint32 sz){catUL2str(buf + 61, sz);} // 4
    void setParametrsLen   (char* buf, quint32 sz){catUL2str(buf + 65, sz);} // 4
    void setOptionsLen     (char* /*buf*/, quint32 /*sz*/){}
    void setCompressed     (char* /*buf*/, bool     /*b*/){}

    void setCompName       (char* buf, const QString& name)
    {strncpy(buf + 69, name.toUtf8().data(), compNameLen(buf));}

    void setUserName       (char* buf, const QString& name) // ??
    {strncpy(buf + 69 + compNameLen(buf), name.toUtf8().data(), userNameLen(buf));}

    void setMessage        (char* buf, const QString& msg) // ??
    {memcpy(buf + 69 + compNameLen(buf) + userNameLen(buf), msg.toUtf8().data(), messageLen(buf));}

    void setParametrs      (char* buf, const QByteArray& pars) // ??
    {memcpy(buf + 69 + compNameLen(buf) + userNameLen(buf) + messageLen(buf), pars.data(), parametrsLen(buf));}
};

#endif
