/* -*- c++ -*-
 *
 * mmpacket.h
 *
 * Copyright (C) 2003 Petter Stokke <ummo@hellokitty.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef __kmldonkey_mobilemule_mmpacket_h__
#define __kmldonkey_mobilemule_mmpacket_h__

#include <qstring.h>
#include <qmemarray.h>
#include <qmap.h>
#include <qvariant.h>

#include "donkeytypes.h"



//opcodes
#define MMP_HELLO			0x01
#define MMP_HELLOANS		0x02
#define	MMP_INVALIDID		0x03
#define	MMP_GENERALERROR	0x04
#define	MMP_STATUSREQ		0x05
#define	MMP_STATUSANSWER	0x06
#define	MMP_FILELISTREQ		0x07
#define	MMP_FILELISTANS		0x08
#define	MMP_FILECOMMANDREQ	0x09
#define	MMP_FILECOMMANDANS	0x10
#define	MMP_FILEDETAILREQ	0x11
#define	MMP_FILEDETAILANS	0x12
#define	MMP_COMMANDREQ		0x13
#define	MMP_COMMANDANS		0x14
#define	MMP_SEARCHREQ		0x15
#define	MMP_SEARCHANS		0x16
#define	MMP_DOWNLOADREQ		0x17
#define	MMP_DOWNLOADANS		0x18
#define MMP_PREVIEWREQ		0x19
#define MMP_PREVIEWANS		0x20
#define MMP_FINISHEDREQ		0x21
#define MMP_FINISHEDANS		0x22
#define MMP_CHANGELIMIT		0x23
#define MMP_CHANGELIMITANS	0x24

// tags
#define	MMT_OK				0x01
#define	MMT_WRONGVERSION	0x02
#define	MMT_WRONGPASSWORD	0x03
#define	MMT_FAILED			0x00
#define MMT_PAUSED			0x00
#define MMT_WAITING			0x01
#define MMT_DOWNLOADING		0x02

#define	MMT_PAUSE			0x03
#define MMT_RESUME			0x02
#define MMT_CANCEL			0x01

#define MMT_SDEMULE			0x01
#define MMT_SDPC			0x02
#define MMT_SERVERCONNECT	0x03
#define MMT_SEARCH			0x30
#define MMT_PREVIEW			0x40

// OK = 0x01
#define MMT_NOTCONNECTED	0x02
#define MMT_TIMEDOUT		0x03
#define MMT_NORESULTS		0x04

// failed = 0x00
// OK = 0x01
#define MMT_NOTAVAILABLE	0x02
#define MMT_NOTSUPPORTED	0x03

#define MMT_PARTFILFE		0x01
#define MMT_FINISHEDFILE	0x02

#define MM_VERSION			0x6b
#define MM_STRVERSION		"0.6b"



class QTextCodec;

class MMPacket : public QMemArray<int8>

{
public:
    //! Construct an empty message with the given opcode.
    /*! \param opcode The message's opcode. */
    MMPacket(int8 opcode);
    //! Construct a message from a memory buffer.
    /*! The buffer must include the opcode as the first byte. */
    MMPacket(const char* data, int len);
    //! Construct a message with the given opcode and length.
    /*! \param opcode The message's opcode.
     *  \param len The message size. */
    MMPacket(int8 opcode, int len);

    //! Set the opcode of the message.
    /*! \param opcode The new opcode. */
    void setOpcode(int8 opcode);
    //! Get the opcode of the message.
    /*! \return The opcode. */
    int8 opcode() const;

    //! Append a byte to the message.
    /*! \param v A byte. */
    void writeByte(int8 v);
    //! Append a 16-bit word to the message.
    /*! \param v A 16-bit word. */
    void writeShort(int16 v);
    //! Append a 32-bit word to the message.
    /*! \param v A 32-bit word. */
    void writeInt(int32 v);
    //! Append a string to the message.
    /*! \param v A string. */
    void writeString(const QString& v);
    //! Append a string to the message.
    /*! \param v A null terminated string buffer. */
    void writeString(const char* v);
    //! Append a byte array to the message.
    /*! \param v A byte array. */
    void writeByteArray(const QByteArray& v);

    //! Append a copy of a memory buffer to the message.
    /*! \param buf A pointer to the start of the buffer.
     *  \param sz The size in bytes of the buffer. */
    void feedBuffer(const char* buf, int sz);
    //! Reset the read position to the start of the message.
    void resetPosition();

    //! Read a byte from the message.
    /*! \return A byte. */
    int8 readByte();
    //! Read a 16-bit word from the message.
    /*! \return A 16-bit word. */
    int16 readShort();
    //! Read a 32-bit word from the message.
    /*! \return A 32-bit word. */
    int32 readInt();
    //! Read a string from the message.
    /*! \return A string. */
    QString readString();
    //! Read a byte array from the message.
    /*! This is essentially the same as reading a string, but it's not processed
     *  by the charset decoder.
     *  \return A byte array. */
    QByteArray readByteArray();

    //! Construct a string containing a hex dump of the message.
    QString dumpArray() const;

    //! Explicitly specify a QTextCodec to use in decoding strings from messages.
    /*! MMPacket defaults to using an ISO-8859-1 codec when translating
     *  strings from the core into internal Unicode representations. If you are
     *  expecting a different charset, you can call this static method to specify
     *  the codec to be used.
     *  \param codec The QTextCodec object to be used in string decoding.
     */
    static void setStringCodec(QTextCodec* codec);

    //! Return the size of the packet, including the opcode.
    uint packetSize() const;

    int16 sessionID() const;
    void setSessionID(int16 id);

    bool specialHeader() const;
    void setSpecialHeader(bool sh);

protected:
    //! The message's opcode.
    int8 op;

private:
    void initCodec();
    void writeInt(int32 v, int sz);
    int32 readInt(int sz);
    int pos;
    static QTextCodec* codec;
    int16 m_sessionID;
    bool m_specialHeader;
};

#endif
