/* 
  NMDCHub
  ŻŻŻŻŻŻŻ
    About: Protocol library for NMDC, the successor to DCBot, DCBot2 and mappyDC.
    Usage: Instantiate NMDCHub and poll NextEvent(), and compare its type with
           NMDCEventTypes to see what happened.
  Depends: STL::queue, STL::map, STL::string, mSock, mUtil
       
*/

#pragma once
#include "../common/mSock.h"
#include <string>

#define NMDC_TAG "mudc V:1"

// NMDCEvent
////////////

enum NMDCEventTypes {
	NMDC_NONE,           /* Nothing to report.       data1: -             data2: -         */
	NMDC_DEBUG_INFO,     /* Debugging information.   data1: undefined     data2: undefined */
	NMDC_PUBLIC_CHAT,    /* A public chat message.   data1: sender nick   data2: message   */
	NMDC_PRIVATE_MSG,    /* A private chat message.  data1: sender nick   data2: message   */
	NMDC_SYSTEM_MSG,     /* A system message.        data1: -             data2: message   */
	NMDC_USER_JOIN,      /* A user joined the hub.   data1: user nick     data2: -         */
	NMDC_USER_PART,      /* A user left the hub.     data1: user nick     data2: -         */
	NMDC_USER_UPDATE,    /* A user updated details.  data1: user nick     data2: -         */
	NMDC_NEED_PASS,		 /* Send a password before doing anything else.                    */
	NMDC_KICKED			 /* We've been removed from the hub.							   */
};
typedef int NMDC_EVENT_TYPE;

class NMDCEvent {
public:
	NMDC_EVENT_TYPE	type;
	std::string		data1;
	std::string		data2;
};

// NMDCUser
///////////

typedef unsigned long long uint64;
class NMDCUser {
public:
	std::string szNick;
	std::string szDescription;
	uint64 iShareSize;
};

// NMDCHub
//////////

struct NMDCHubData;

class NMDCHub {
private:
	NMDCHubData * _d;

public:
	// De/Construction
	NMDCHub(const char* szAddress, int iPort, const char* szNick, uint64 iShareSize);
	NMDCHub(const char* szAddress, const char* szNick, uint64 iShareSize); //will detect port in address
	~NMDCHub();
	void Disconnect();

	// Public methods
	bool Connected();
	void Login(const char* szPassword);
	void SayPublic(const char* szMessage);
	void SayPrivate(const char* szUsername, const char* szMessage);
	void SayExplicit(const char* szMessage);

	// Event handling
	NMDCEvent NextEvent();

	// User handling
	int  GetUserCount();
	void GetUserNicks(NMDCUser* arrayDest, int maxcount);
	bool GetUserInfo(const char* szUsername, NMDCUser* out);
	NMDCUser GetUserSelf();

private:
	// De/Construction
	void Initialise(const char* szAddress, int iPort, const char* szNick, uint64 iShareSize);

	// Event handling	
	void push_event(int iType, const char* data1, const char* data2);

	// Protocol handlers
	void handle_command(std::string &szCommand);
	void process_messages();

	// Protocol helpers
	void        chatSanitise(std::string& message);
	void        chatDesanitise(std::string& message);
	void		joinUser(NMDCUser usr);
	void		joinUser(const char* szNick);
	NMDCUser	parse_myinfo(const char* myinfo);
	void		parse_to(const char* to);
	std::string parse_lock(const char *lock);
	void		parse_nicklist(const char* list);

};
