/**
* @brief
websocket�ͻ�����

* @version
  V 1.0.0

* @author
  ���濡

* @date
  ����ʱ��:  2018-08-14\n

* @note
  2018-08-14  �����ࡣ\n

* @warning

* @bug
  
*/

#pragma once

#include <string>
#include <mutex>
#include <condition_variable>
#include <map>

#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/prettywriter.h>

#include <boost/function.hpp>
#include <boost/bind.hpp>

#include "sio_client.h"
#include "jsonBuilder.h"

namespace YA
{
	//��Ϣ������������
	typedef boost::function<void( int, std::string const&, sio::message::ptr const&, bool, sio::message::list & )> MSG_HANDLE_FUNC_TYPE;

	class wsClient
	{
	private:
		sio::client __wsclient;//websocket�ͻ���
		int __ID;//Ψһ��ʶ
		std::string __uri;//�����ַ���
		bool __Connected;//�Ƿ������Ϸ�������
		bool __SktOpened;//Socket�Ƿ��Ѵ�
		bool __Logined;//�Ƿ��ѵ�¼�ɹ�
		std::condition_variable_any __cond;//��������
		std::mutex __lock;//��(���__cond)
		std::string __LastError;//���´���
		std::map<std::string, MSG_HANDLE_FUNC_TYPE> __MsgFuncList;//��Ϣ���������б�(key������,value�Ǵ�������)
		std::recursive_mutex __send_lock;//������
		jsonBuilder __jsBuilder;//json������
	protected:
		/**
		* @brief
		����״̬������

		* @param  ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _reset();
		/**
		* @brief
		���ӳɹ��ص�������

		* @param  ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _on_connected();
		/**
		* @brief
		���ӹرջص�������

		* @param  [in] sio::client::close_reason const& reason �رյ�ԭ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _on_close( sio::client::close_reason const& reason );
		/**
		* @brief
		�����ص�������

		* @param  [in] unsigned p1 ???\n
		* @param  [in] unsigned p2 ???\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _on_reconnect( unsigned p1, unsigned p2 );
		/**
		* @brief
		ʧ�ܻص�������

		* @param  ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _on_fail();
		/**
		* @brief
		socket�򿪳ɹ��ص�������

		* @param  ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _on_socket_opened();
		/**
		* @brief
		�յ���������CALL����ص�������

		* @param  [in] std::string const& name  ����������\n
		* @param  [in] sio::message::ptr const& data  �յ�����Ϣ����\n
		* @param  [in] bool need_ack  �Ƿ���ҪӦ��\n
		* @param  [in] sio::message::list &ack_resp  Ӧ����Ϣ����\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _OnCallMessage( std::string const& name, sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp );
		/**
		* @brief
		�յ��������˵�¼Ӧ������ص�������

		* @param  [in] std::string const& name  ����������\n
		* @param  [in] sio::message::ptr const& data  �յ�����Ϣ����\n
		* @param  [in] bool need_ack  �Ƿ���ҪӦ��\n
		* @param  [in] sio::message::list &ack_resp  Ӧ����Ϣ����\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void _OnLoginResponse( std::string const& name, sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp );
	public:
		wsClient();
		~wsClient();
		/**
		* @brief
		��ʼ��������

		* @param  [in] int ID  ��ǰ�ͻ��˵�Ψһ��ʶ\n
		* @param  [in] const std::string & uri  ���Ӵ�\n
		* @param  [in] const std::map<std::string, MSG_HANDLE_FUNC_TYPE>& MsgFuncList  ��Ϣ��������\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void init( int ID, const std::string & uri, const std::map<std::string, MSG_HANDLE_FUNC_TYPE>& MsgFuncList );
		/**
		* @brief
		��������ַ���������

		* @param  ��\n

		* @return ��õ������ַ���\n

		* @note

		* @warning

		* @bug

		*/
		std::string get_uri();
		/**
		* @brief
		�����Ӻ�����

		* @param  [in] int time_out  ��ʱ(��λ����),Ĭ����3��\n

		* @return ���ӷ������Ƿ�ɹ�\n
		* @retval  0  �ɹ�\n
        * @retval  -1  ʧ��\n

		* @note

		* @warning

		* @bug

		*/
		int connect( int time_out = 3 );
		/**
		* @brief
		����¼������

		* @param  ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void login();
		/**
		* @brief
		�������ݺ�����

		* @param  [in] const std::string & Cmd  Ҫ���͵�����\n
		* @param  [in] const std::string& Data  Ҫ���͵�����\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void send( const std::string & Cmd, const std::string & Data );
		/**
		* @brief
		���ID������

		* @param  ��\n

		* @return ��õ�ID\n

		* @note

		* @warning

		* @bug

		*/
		int GetID();
		/**
		* @brief
		����Ƿ������ӷ������˺�����

		* @param  ��\n

		* @return �Ƿ������ӷ�����\n

		* @note

		* @warning

		* @bug

		*/
		bool IsConnected();
		/**
		* @brief
		���Socket�Ƿ��Ѵ򿪺�����

		* @param  ��\n

		* @return Socket�Ƿ��Ѵ�\n

		* @note

		* @warning

		* @bug

		*/
		bool IsSktOpened();
		/**
		* @brief
		����Ƿ��ѵ�¼�ɹ�������

		* @param  ��\n

		* @return �Ƿ��ѵ�¼�ɹ�\n

		* @note

		* @warning

		* @bug

		*/
		bool IsLogined();
		/**
		* @brief
		�رպ�����

		* @param  ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		void close();
		/**
		* @brief
		������´�������

		* @param  ��\n

		* @return ��\n

		* @note

		* @warning

		* @bug

		*/
		std::string GetLastError();
	};
}