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

#include <abstractprotocol.h>

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

  public:
    ProtocolVersion4();

    ~ProtocolVersion4();
    // Protocol information functions
    uint  protocolVersion() const {return 4;}
    uint  protocolLen    () const {return 57;}
    const char* programId() const {return m_programId;}
    uint optionsLen() const {return 1;}

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

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

    uint    packetSize      (const char* buf){return str2US (buf + 5);} // 2 bytes

    uint    programVersion  (const char* buf){return str2US (buf + 7);} // 2
    uint    protocolVersion (const char* buf){return str2US (buf + 9);} // 2
    quint64 destIp          (const char* buf){return str2ULL(buf + 11);} // 8
    quint64 srcIp           (const char* buf){return str2ULL(buf + 19);} // 8
    uint    packetType      (const char* buf){return       *(buf + 27);} // 1
    uint    packetId        (const char* buf){return str2US (buf + 28);} // 2
    uint    fragmentSize    (const char* buf){return str2US (buf + 30);} // 2
    uint    packetNum       (const char* buf){return str2UL (buf + 32);} // 4
    quint64 time            (const char* buf){return str2ULL(buf + 36);} // 8
    uint    channelType     (const char* buf){return       *(buf + 44);} // 1
    uint    compNameLen     (const char* buf){return       *(buf + 45);} // 1
    uint    userNameLen     (const char* buf){return       *(buf + 46);} // 1
    uint    messageLen      (const char* buf){return str2UL (buf + 47);} // 4
    uint    parametrsLen    (const char* buf){return str2UL (buf + 51);} // 4
    uint    optionsLen      (const char* buf){return str2US (buf + 55);} // 2

    bool    compressed      (const char* buf){if(optionsLen(buf) < 1) return false; return buf[57] & 128;}

    QByteArray options      (const char* buf, uint sz);
    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(), 5);}
    void setPacketSize     (char* buf, uint sz){catUS2str(buf + 5, sz);} // 2 bytes
    void setProgramVersion (char* buf){catUS2str(buf + 7, Globals::VersionID);}
    void setProtocolVersion(char* buf){catUS2str(buf + 9, protocolVersion());}

    void setDestIp         (char* buf, quint64 ip){catULL2str(buf + 11, ip);} // 8
    void setSrcIp          (char* buf, quint64 ip){catULL2str(buf + 19, ip);} // 8
    void setPacketType     (char* buf, uint  type){          (buf[27] = type);} // 1
    void setPacketId       (char* buf, uint    id){catUS2str (buf + 28, id);} // 2
    void setFragmentSize   (char* buf, uint    sz){catUS2str (buf + 30, sz);} // 2
    void setPacketNum      (char* buf, quint32 nm){catUL2str (buf + 32, nm);} // 4
    void setTime           (char* buf, quint64 tm){catULL2str(buf + 36, tm);} // 8
    void setChannelType    (char* buf, quint32 id){buf[44] = id;} // 1
    void setCompNameLen    (char* buf, uint    sz){buf[45] = sz;} // 1
    void setUserNameLen    (char* buf, uint    sz){buf[46] = sz;} // 1
    void setMessageLen     (char* buf, quint32 sz){catUL2str(buf + 47, sz);} // 4
    void setParametrsLen   (char* buf, quint32 sz){catUL2str(buf + 51, sz);} // 4
    void setOptionsLen     (char* buf, quint32 sz = 1){catUS2str(buf + 55, sz);} // 2

    void setCompressed     (char* buf, bool     b){ b ? buf[57] |= 128 : buf[57] &= 127;}

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

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

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

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

#endif
