/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef P2PMESSAGE_H
#define P2PMESSAGE_H

#include "mimemessage.h"

/**
 * A message using MSN P2P protocol.
 *
 * @author Michael Jarrett (JudgeBeavis@hotmail.com), Diederik van der Boor (vdboor --at-- codingdomain.com)
 */
class P2PMessage : private MimeMessage
{
Q_OBJECT

public:  // Enums

  enum MsnP2PFlags
  {
    MSN_FLAG_ACK          = 0x02,     // P2P Message is an ACK
    MSN_FLAG_WAITING      = 0x04,     // Other client is waiting for a reply
    MSN_FLAG_ERROR        = 0x08,     // Error (possibly at binary level)
    MSN_FLAG_DATA         = 0x20,     // Picture data
    MSN_FLAG_CLOSING_ACK  = 0x40,     // All data received ACK (A send BYE, B send ACK, A sends this message).
    MSN_FLAG_BYE_SENT     = 0x80,     // Bye ack (He who sent BYE)
    MSN_FLAG_FILETRANSFER = 0x1000030 // File transfer (is: 0x10 | 0x20 | 0x1000000)
  };

public:  // Constructors
  /**
   * Build an (empty) P2P message.
   */
  P2PMessage();

  /**
   * Build a P2P message based on a string received from the switchboard.
   * @param read The full message from the switchboard, including all the mime-y
   *             stuff.
   */
  P2PMessage(const MimeMessage &mimeMessage);


public:    // Accessors
  /**
   * Sets the message body.
   * Overrides non-virtual setBody in MimeMessage, adding our own P2P goodness.
   */
  void setBody(const QString &body);

  /** Retreives the current session ID. */
  unsigned long getSessionID() const;
  /** Retreives the current message ID. */
  unsigned long getMessageID() const;
  /** Retreives the current data message offset. */
  unsigned long getDataOffset() const;
  /** Retreives the current data message size. */
  unsigned long getDataSize() const;
  /** Retreives the message flags. */
  unsigned long getFlags() const;
  /** Retreives the total message size. */
  unsigned long getTotalSize() const;
  /** Retrieves the ack message ID field. */
  unsigned long getAckMessageID() const;
  /** Retreives the ack unique ID field. */
  unsigned long getAckUniqueID() const;
  /** Retreives the ack data size field. */
  unsigned long getAckDataSize() const;

  // Make the getMessage method (from our private base class) available.
  using MimeMessage::getMessage;
  // Make the getValue method available
  using MimeMessage::getValue;

  /** Retreives the actual data. */
  char *getData() const;

  /** Returns true if the ACK flag is set */
  bool isAck() const;
  /** Returns true if the message is the last ACK (A send BYE, B send ACK, A sends this message) */
  bool isClosingAck() const;
  /** Returns true if the binary-error flag is set. */
  bool isError() const;
  /** Returns true if the BYE-ACK is set (he who sent BYE) */
  bool isSentByeAck() const;
  /** Return true if the file-data flag is set. */
  bool isFileData() const;
  /** Return true if this is an fragment (splitted message packet. */
  bool isFragment() const;
  /** Return true if this is the last part of a message. */
  bool isLastFragment() const;
  /** Return true if the picture-data flag is set. */
  bool isPictureData() const;
  /** Returns true of the waiting-for-reply flag is set */
  bool isWaiting() const;


  /** Copy integers into the binary header. */
  static          void insertBytes(QByteArray& buffer, const unsigned int value, const int offset);
  /** Copy sort integers into the binary header. */
  static          void insertShortBytes(QByteArray &buffer, const unsigned short value, const int offset);
  /** Extracts the bytes from the data block. */
  static unsigned int  extractBytes(const char *data, const int offset);
  /** Extracts the bytes from the data block. */
  static unsigned long extractLongBytes(const char *data, const int offset);


private:    // Helper functions
  void parseP2PHeader(); ///< Extract the fields from the P2P binary header.


private:    // Data
  QString messageBody_;

  // Session ID identifying which (MSN-)SLP we're dealing with.
  unsigned long sessionID_;
  // Message ID identifying which message packet we're dealing with.
  unsigned long messageID_;
  // Message offset.. (message packets can be split)
  unsigned long dataOffset_;
  // Message size..
  unsigned long dataSize_;
  // Message flags.
  unsigned long flags_;
  // Total message size
  unsigned long totalSize_;
  // Ack session id.
  unsigned long ackMessageID_;
  // Ack Unique id.
  unsigned long ackUniqueID_;
  // Ack data size.
  unsigned long ackDataSize_;
};


#endif
