#ifndef O2ON_CHAT_H_INCLUDED
#define O2ON_CHAT_H_INCLUDED

#include <string>
#include <list>
#include <vector>
#include <deque>
#include <queue>
#include <map>
#include <boost/noncopyable.hpp>

#include "p2p.h"
#include "define.h"

class ChatMessage {
public:
	ChatMessage(const std::string& name, const std::string& message, const std::string& guid,
		time_t time, const std::string& id, const std::string& sign, int ttl = -1)
		: name_(name), message_(message), guid_(guid), time_(time), id_(id), sign_(sign),
		ttl_(ttl) { sanitize(name_); sanitize(message_); };
	const std::string toXmlString() const;
	const std::string getName() const { return name_; }
	const std::string getMessage() const { return message_; }
	const time_t getTime() const { return time_; }
private:
	std::string name_, message_, guid_, id_, sign_;
	time_t time_;
	int ttl_;
	void sanitize(std::string& str);
};

class CriticalSection : boost::noncopyable {
public:
	CriticalSection() { InitializeCriticalSection(&cs); }
	~CriticalSection() { DeleteCriticalSection(&cs); }
private:
	CRITICAL_SECTION cs;
	friend class Lock;
};

class Lock : boost::noncopyable {
public:
	Lock(CriticalSection& cs) : cs_(cs) { EnterCriticalSection(&cs_.cs); }
	~Lock() { LeaveCriticalSection(&cs_.cs); }
private:
	CriticalSection& cs_;
};

/*!
	@brief Chat Processor
*/
class ChatProcessor : boost::noncopyable {
public:
	void setServer(TCPServer<TCPSocketBuffer<TimedTCPSocket>, ChatProcessor>* server) { server_ = server; }
	void acceptDetected();
	bool recvDetected(TCPSocketBuffer<TimedTCPSocket>& sockbuf);
	void disconnected();
	void dosomething(std::list<TCPSocketBuffer<TimedTCPSocket> >& sockets);
	void startProcessor();

	ChatProcessor(unsigned short chat_port) : server_(0), chat_port_(chat_port)
	{ FD_ZERO(&waitingFd); }
	~ChatProcessor();
	void queueChatMessage(const std::string& name, const std::string& message);
	size_t getNodessize() const { return nodes.size(); }
	void pushNode(const NodeInfo& node);
	unsigned short getChatport() const { return chat_port_; }
	std::deque<ChatMessage>& getMessages() { return messages; }
	CriticalSection& getMsgCS() { return cs_msgs; }
	CriticalSection& getMsgqCS() { return cs_msgq; }
	std::deque<std::string>& getProcessed() { return processed; }
	std::queue<ChatMessage>& getMsgqueue() { return msgqueue; } // インターフェースを…

private:
	//bool parseProtocol(TCPSocketBuffer<TimedTCPSocket>& s);
	void outboundHandshake(const TCPSocket& s, unsigned short myport, unsigned long yourip);
	//void mapXmlAttribute(const MSXML2::IXMLDOMNodePtr& attr,
	//	std::map<std::string, std::string>& dest);
	void sendNodes(const TCPSocket& s, std::vector<NodeInfo>& nodes);

	TCPServer<TCPSocketBuffer<TimedTCPSocket>, ChatProcessor>* server_;
	fd_set waitingFd;
	std::vector<SOCKET> waitingSockets;	//!< 接続待ちソケット用
	std::queue<ChatMessage> msgqueue;
	std::deque<std::string> processed;
	std::deque<ChatMessage> messages;
	CriticalSection cs_msgq, cs_nodes, cs_msgs;
	//MSXML2::IXMLDOMDocument2Ptr pDoc;
	std::vector<NodeInfo> nodes;
	unsigned long global_ip;
	unsigned short chat_port_;
	time_t pretime;
};

extern TCPServer<TCPSocketBuffer<TimedTCPSocket>, ChatProcessor>* pchatservent;

unsigned int __stdcall chat_thread(void * /*data*/);
BOOL __stdcall chat_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);

#endif /* O2ON_CHAT_H_INCLUDED */
