#pragma once
#include "bridgeserver_h.h"
#include "bridgeclient_h.h"
#include <list>
#include "message.h"

class ClientContext
{
public:
	ClientContext(int userId, const TCHAR * username, const TCHAR * machinename, const TCHAR * port);
	~ClientContext(void);

	// These static routines maintain the context list.
	// To create and delete ClientContext objects you MUST use these.
	static HANDLE Mutex; // serializes modify-access to the list of contexts
	static ClientContext * Create(int userId, const TCHAR * username, const TCHAR * machinename, const TCHAR * port);
	static int Delete(ClientContext * context);
	static ClientContext * Find(int userId);
	static ClientContext * Find(ClientContext * ptr);
	static std::list<ClientContext *> contexts; // the global list of all contexts
	static int ClientContextCount;
	static DWORD WINAPI StartContextPump(LPVOID p);

	
	// these static routines broadcast various types of notifies to subsets of the users
	static void Notify(int userId, int type, int theId, int reason, int param);
	static void Notify(Vector<int> recipients, int type, int theId, int reason, int param, int except = -1);
	static void NotifyWatchers(int userId, int type, int theId, int reason, int param, int except = -1);
	static void NotifyOnlineUsers(int type, int theId, int reason, int param, int except = -1);
	static void NotifyGroupMembers(int groupId, int type, int theId, int reason, int param, int except = -1);
	static void NotifyEventMembers(int eventId, int type, int theId, int reason, int param, int except = -1);
	static void NotifyEventCanViews(int eventId, int type, int theId, int reason, int param, int except = -1);

	// Send messages to the client	
	void PostMessage(Message& msg); // creates a copy of the message
	int PostMessageAndWait(Message& msg, int timeout); // 

	// the user associated with this context
	int userId;
	std::wstring username;
	
	BRIDGECLIENT_SERVICE_INFO client; // network info abbut the client service connection

	// tell the message pump to quit
	void Die();

private:
	//// RPC calls to the client service that is associated with this context
	// the BridgeServer calls this to notify the BridgeClient of a chat message
	void InstantMessageNotify(int senderId,
		/*[in,string]*/ const TCHAR * sender, 
		int recipientId,
		/*[in,string]*/ const TCHAR * recipient, 
		/*[in,string]*/ const TCHAR * msg);
	void GroupMessageNotify(int senderId, /*[in,string]*/ const TCHAR * sender, 
	/*[in]*/ int groupId, 
	const TCHAR * group,
	/*[in,string]*/ const TCHAR * msg);

	// the BridgeServer calls these to notify the BridgeClient of changes
	void ClientNotify(/*[in]*/ int type,/*[in]*/ int theId, /*[in]*/ int reason, int param);

	///// Elements of the Message Pump
	HANDLE hThread; // the identifier of this message pump's thread
	std::list<Message*> Q; // the message queue
	int MessagePump(); // the message pump for this context (runs in its own thread)
	int dead;
	HANDLE MessageNotify; // the message notify event

	CRITICAL_SECTION CriticalSection; 
};
