/***************************************************************************
                          cmessagedc.h  -  description
                             -------------------
    begin                : Fri May 9 2003
    copyright            : (C) 2003 by Daniel Muller
    email                : dan at verliba dot cz
 ***************************************************************************/

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

/**a dc Message incomming or outgoing
  *@author Daniel Muller
  */

#include <string>
#include <sstream>
#include <vector>
#include "cobj.h"
#include "cprotocommand.h"

using namespace std;
namespace nDirectConnect {
namespace nProtocol {

namespace nEnums {
// these constants correspond to sDC_Commands in the .cpp file
typedef enum
{
	eDC_GETINFO,
	eDC_SEARCH_PAS,
	eDC_SEARCH,
	eDC_SR,
	eDC_MYNIFO,
	eDC_KEY,
	eDC_VALIDATENICK,
	eDC_MYPASS,
	eDC_VERSION,
	eDC_GETNICKLIST,
	eDC_CONNECTTOME,
	eDC_MCONNECTTOME,
	eDC_RCONNECTTOME,
	eDC_TO,
	eDC_CHAT,
	eDC_QUIT,
	eDC_OPFORCEMOVE,
	eDC_KICK,
	eDC_MSEARCH_PAS,
	eDC_MSEARCH,
	eDCE_SUPPORTS,
	eDCM_NETINFO,
	eDCO_BAN,
	eDCO_TBAN,
	eDCO_UNBAN,
	eDCO_GETBANLIST,
	eDCO_WHOIP,
	eDCO_BANNED,
	eDCO_SETTOPIC,
	eDCO_GETTOPIC,
	eDCB_BOTINFO,
	eDC_UNKNOWN,
	eDC_UNPARSED
} tDCMsg;

/** Following constants design the placements of corresponding attribute of every
	DC protocol message comming from the client... in the mChunks,
	these are used in the cDCServer::DC_* functions
	and also in the cMessageDC::SplitChunks ... they must be corresponding
	 */
// chunk numbers for simple commands
enum { eCH_0_ALL }; // eDC_GETNICKLIST
// chunk numbers for cmd with one param only
enum { eCH_1_ALL, eCH_1_PARAM }; //KEY VALIDATENICK VERSION MYPASS QUIT KICK UNBAN
// -----*** chunk numbers for all other ***-----
// chat
enum { eCH_CH_ALL, eCH_CH_NICK, eCH_CH_MSG };
// GetINFO
enum { eCH_GI_ALL, eCH_GI_OTHER, eCH_GI_NICK };
// RevConnectToMe   $RevConnectToMe <nick> <remoteNick>
enum { eCH_RC_ALL, eCH_RC_NICK, eCH_RC_OTHER };
// private chat : CHMSH is a "<nick> msg" together
enum { eCH_PM_ALL, eCH_PM_TO, eCH_PM_FROM, eCH_PM_CHMSG, eCH_PM_NICK, eCH_PM_MSG } ;
// MyINFO : INFO is all the rest together
enum { eCH_MI_ALL, eCH_MI_DEST, eCH_MI_NICK, eCH_MI_INFO, eCH_MI_DESC, eCH_MI_SPEED, eCH_MI_MAIL, eCH_MI_SIZE };
/// connecttome   $ConnectToMe <remoteNick> <senderIp>:<senderPort>
enum {eCH_CM_ALL, eCH_CM_NICK, eCH_CM_ACTIVE, eCH_CM_IP, eCH_CM_PORT};
//OpForce move
enum {eCH_FM_ALL, eCH_FM_NICK, eCH_FM_DEST, eCH_FM_REASON };
// active search
enum {eCH_AS_ALL, eCH_AS_ADDR, eCH_AS_IP, eCH_AS_PORT, eCH_AS_QUERY};
// passive search
enum {eCH_PS_ALL, eCH_PS_NICK, eCH_PS_QUERY};
// search result $SR <resultNick> <filepath>^E<filesize> <freeslots>/<totalslots>^E<hubname> (<hubhost>[:<hubport>])^E<searchingNick>
enum {eCH_SR_ALL, eCH_SR_FROM, eCH_SR_PATH, eCH_SR_SIZE, eCH_SR_SLOTS, eCH_SR_SL_FR, eCH_SR_SL_TO, eCH_SR_HUBINFO, eCH_SR_TO};
// $NetInfo slots$hubs$active|
enum {eCH_NI_ALL, eCH_NI_SLOTS, eCH_NI_HUBS, eCH_NI_ACTIVE};
// $Ban nick$reason
// $TempBan nick$time$reason
enum {eCH_NB_ALL, eCH_NB_NICK, eCH_NB_REASON, eCH_NB_TIME};

};

using namespace nDirectConnect::nProtocol::nEnums;

/**
* The Direct Connect Protocol Message parser and container
* provides access to all important parts of the message as std::string
*/
class cMessageDC : public cObj
{
public:
	cMessageDC();
	virtual ~cMessageDC();
	/** parses the string and sets the state variables */
	virtual int Parse();
	/** return the n'th chunk (as splited by SplitChunks) function */
	string &ChunkString(unsigned int n);
	/** apply the chunkstring ito the main string */
	void ApplyChunk(unsigned int n);
	/** splits message to it's important parts and stores their info in the chunkset mChunks */
	bool SplitChunks();
	/** get string */
	string & GetStr();
	/** reinitialize the structure */
	void ReInit();

public: // Public attributes
	/** The actual message string */
	string mStr;
	/** indicates if the message is tooo long so it can't be receved complete */
	bool Overfill;
	/** indicates if the message is completely received */
	bool Received;
	/** error in message indicator */
	bool mError;
	/** parsed message type */
	tDCMsg mType;
	/** the length of weyword and thus the relative position of the first parameter */
	int mKWSize;
	/** length of the message */
	unsigned int mLen;

	/** the type for message chunks */
	typedef pair<int,int> tChunk;
	typedef vector<tChunk> tChunkList;
	typedef tChunkList::iterator tCLIt;
	typedef vector<string *> tStrPtrList;
	typedef tStrPtrList::iterator tSPLIt;
	/** the list of chunks */
	tChunkList mChunks;
	/** list of string pointers */
	//tStrPtrList mChStrings;
	string mChStrings[20];
	/** a bitmap having information about chStringsSet */
	unsigned long mChStrMap;

private: // Private methods
	/** reduce the chunk from left by amount, cn is the chunk number */
	void ChunkRedLeft(int cn, int amount);
	/** splits message into two chunks by a delimiter adn stores them in the chunklist */
	bool SplitOnTwo(size_t start, const char lim, int cn1, int cn2, size_t len=0,bool left=true);
	/** splits the chunk number "ch" into two chunks by a delimiter adn stores them in the chunklist under numbers cn1 and cn2 */
	bool SplitOnTwo(const char lim, int ch, int cn1, int cn2, bool left=true);
	/** reduce the chunk from right by amount, cn is the chunk number */
	void ChunkRedRight(int cn, int amount);
	/** the static buffer saving memory and allocations */
	static char *mBuffer;
	static const int msBuffSize;
	static int msCounterMessageDC;
protected: // Protected methods
	/** fill in a given chunk */
	void SetChunk(int,int,int);
};
};
};

#endif
