/***************************************************************************
 *   Copyright (C) 2004 by yunfan                                          *
 *   yunfan_zg@163.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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef EVA_RECEIVE_IM_PACKET_H
#define EVA_RECEIVE_IM_PACKET_H

#include "evapacket.h"
#include <string>


#define REPLY_KEY_LENGTH 16
class ReceiveIMPacket :public InPacket
{
public: 
	ReceiveIMPacket() {}
	ReceiveIMPacket(unsigned char *buf, const int len);
	ReceiveIMPacket(const ReceiveIMPacket &rhs);
	~ReceiveIMPacket() {};
	
	const int getSender() const { return sender; }
	const int getReceiver() const { return receiver; }
	const int getIntSequence() const { return intSequence; }
	const int getSenderIP() const { return senderIP; }
	const short getSenderPort() const { return senderPort; }
	const short getIMType() const { return type; }
	
	const char *getReplyKey() const { return replyKey; }
	const int getBodyLength() const { return (bodyLength - bodyOffset); }
	const unsigned char *getBodyData() const { return (decryptedBuf + bodyOffset); }
	
	static std::string convertToShow(const std::string &src);
	ReceiveIMPacket &operator=(const ReceiveIMPacket &rhs);
protected:
	virtual void parseBody(); 

private:
	char replyKey[REPLY_KEY_LENGTH];
	// these are the header information
	int sender;
	int receiver;
	int intSequence;
	int senderIP;  // 4 bytes for 4 parts of a IP adress
	short senderPort;
	short type;
	
	int bodyOffset;
	int readHeader(const unsigned char * buf);
};

class ReceivedSystemIM{
public:
	ReceivedSystemIM(const unsigned char *buf, const int len);
	ReceivedSystemIM( const ReceivedSystemIM &rhs);
	~ReceivedSystemIM() {};
	
	const unsigned char getSystemIMType() const { return systemIMType; }
	const std::string &getMessage() const { return message; }
	ReceivedSystemIM &operator=(const ReceivedSystemIM &rhs);
private:
	unsigned char systemIMType;
	std::string message;
	void parseData(const unsigned char *buf, const int len);
};

class NormalIMBase{
public:
	NormalIMBase() {}
	NormalIMBase(const unsigned char *buf, const int len);
	NormalIMBase(const NormalIMBase &rhs);
	virtual ~NormalIMBase();

	void setNormalIMBase(const NormalIMBase *base);	
	const unsigned char *getBodyData() const { return bodyBuf; }
	const int getBodyLength() const { return bodyLength; }
	
	const short getSenderVersion() const { return senderVersion; }
	const int getSender() const { return sender; }
	const int getReceiver() const { return receiver; }
	const unsigned char *getBuddyFileSessionKey() const { return fileSessionKey; }
	const short getNormalIMType() const { return type; }
	const short getSequence() const { return sequence; }
	const int getSendTime() const { return sendTime; }
	const char getUnknown1() const { return unknown1; }
	const short getSenderFace() const { return senderFace; }
	
	void parseData();
	
	NormalIMBase &operator=(const NormalIMBase &rhs);
protected:
	virtual void parseContents(const unsigned char *buf, const int len);
	unsigned char *bodyBuf;
	int bodyLength;
private:
	short senderVersion;
	int sender;
	int receiver;
	unsigned char fileSessionKey[16];
	short type;
	short sequence;
	int sendTime;
	char unknown1;
	short senderFace;
	int readHeader(const unsigned char * buf);
};

class ReceivedNormalIM : public NormalIMBase {
public:
	ReceivedNormalIM() {}
	ReceivedNormalIM(const unsigned char *buf, const int len);
	ReceivedNormalIM(const ReceivedNormalIM &rhs);
	virtual ~ReceivedNormalIM() {};
	
	const char *getUnknown2() const { return unknown2; }
	const char *getUnknown3() const { return unknown3; }
	const char getReplyType() const { return replyType; }
	const std::string getMessage() const { return message; }
	const bool hasFontAttribute() const { return mHasFontAttribute; }
	const short getEncoding() const { return encoding; }
	const char getRed() const { return red; }
	const char getGreen() const { return green; }
	const char getBlue() const { return blue; }
	const char getFontSize() const { return fontSize; }
	const std::string &getFontName() const { return fontName; }
	const bool isBold() const { return bold; }
	const bool isItalic() const { return italic; }
	const bool isUnderline() const { return underline; }
	
	const bool isNormalReply() const; // true, it is normal reply, otherwise autoreply (because only two values for replyType)
	ReceivedNormalIM &operator=(const ReceivedNormalIM &rhs);
protected:
	virtual void parseContents(const unsigned char *buf, const int len);
private:
	char unknown2[3];
	char unknown3[4];
	char replyType;
	std::string message;
	
	bool mHasFontAttribute;
	short encoding;
	char red, green, blue;
	char fontSize;
	std::string fontName;
	bool bold, italic, underline;
};

class ReceiveIMReplyPacket : public OutPacket 
{    
public:
	ReceiveIMReplyPacket() {}
	ReceiveIMReplyPacket(const char * key);
	ReceiveIMReplyPacket(const ReceiveIMReplyPacket &rhs);
	virtual ~ReceiveIMReplyPacket() {};
	
	virtual OutPacket *copy(){ return new ReceiveIMReplyPacket(*this);}
	ReceiveIMReplyPacket &operator=(const ReceiveIMReplyPacket &rhs);
	
	const char *getReplyKey() const { return replyKey; }

protected:
	virtual int putBody(unsigned char *buf);
private:
	char replyKey[REPLY_KEY_LENGTH];
};

class ReceivedQunIM{
public:
	ReceivedQunIM(const short src, const unsigned char *buf, const int len);
	ReceivedQunIM( const ReceivedQunIM &rhs);
	ReceivedQunIM() {};
	
	const short getUnknown1() const { return unknown1; }

	const short getSource() const { return source; }
	const int getExtID() const { return externalID; }
	const int getQunID() const { return qunID; } // only for temporary Qun message
	const char getType() const { return type; }
	const int getSenderQQ() const { return sender; }
	const short getSequence() const { return sequence; }
	const int getSentTime() const { return sentTime; }
	const short getVersionID() const { return versionID; }
	const std::string getMessage() const { return message; }
	
	const bool hasFontAttribute() const { return mHasFontAttribute; }
	const short getEncoding() const { return encoding; }
	const char getRed() const { return red; }
	const char getGreen() const { return green; }
	const char getBlue() const { return blue; }
	const char getFontSize() const { return fontSize; }
	const std::string &getFontName() const { return fontName; }
	const bool isBold() const { return bold; }
	const bool isItalic() const { return italic; }
	const bool isUnderline() const { return underline; }
	
	ReceivedQunIM &operator=(const ReceivedQunIM &rhs);
private:
	short source;  // this is to mention,  permenent, temporary qun 
	int externalID;
	int qunID; // for temporary Qun message only
	char type;
	int sender;
	short unknown1;
	short sequence;
	uint sentTime;
	int versionID;
	std::string message;
	
	bool mHasFontAttribute;
	short encoding;
	char red, green, blue;
	char fontSize;
	std::string fontName;
	bool bold, italic, underline;
	
	void parseData(const unsigned char *buf, const int len);
};


/*
	this class is used to analyse following notifications:
	
	QQ_RECV_IM_CREATE_QUN
	QQ_RECV_IM_ADDED_TO_QUN
	QQ_RECV_IM_DELETED_FROM_QUN
	QQ_RECV_IM_REQUEST_JOIN_QUN
	QQ_RECV_IM_APPROVE_JOIN_QUN
	 QQ_RECV_IM_REJECT_JOIN_QUN
	 
	 note that:  
	 	QQ_RECV_IM_CREATE_QUN
		QQ_RECV_IM_ADDED_TO_QUN
		QQ_RECV_IM_DELETED_FROM_QUN
		have no messages in its packet.
*/
class ReceivedQunIMJoinRequest{
public:
	ReceivedQunIMJoinRequest(const unsigned char *buf, const int len);
	ReceivedQunIMJoinRequest( const ReceivedQunIMJoinRequest &rhs);
	ReceivedQunIMJoinRequest() {};

	const int getExtID() const { return externalID; }
	const int getSender() const { return sender; }
	const std::string &getMessage() const { return message; }
	const char getType() const { return type; }
	
	ReceivedQunIMJoinRequest &operator=(const ReceivedQunIMJoinRequest &rhs);
private:
	int externalID;
	int sender;
	unsigned char type;
	std::string message;
};

class SignatureChangedPacket{
public:
	SignatureChangedPacket(const unsigned char *buf, const int len);
	SignatureChangedPacket( const SignatureChangedPacket &rhs);
	~SignatureChangedPacket() {};
	
	const int getQQ() const { return qq; }
	const int getTime() const { return time; }
	const std::string &getSignature() const { return signature; }
	SignatureChangedPacket &operator=(const SignatureChangedPacket &rhs);
private:
	int qq;
	int time;
	std::string signature;
	void parseData(const unsigned char *buf, const int len);
};
#endif

