

/*
 * communication_socket_base 通信模块的基类,
 * 用户从这个基类继承, 初始化之后, 便可以自动进行通信
 * 重载解析消息和封装消息,
 *
 *Thread_safe_list<Binary_buf*> 使用 Binary_buf , 而不是string
 * 主要是为了支持直接发送数字0
 * 
 * 
 * */

#ifndef __COMMUNICATION_SOCKET_BASE__HH__
#define __COMMUNICATION_SOCKET_BASE__HH__

#include <mutex>
#include <thread>
#include <nnxx/message>
#include <nnxx/socket.h>
#include <nnxx/bus.h>

#include <glog/logging.h>
#include "../error_code/error_code.h"
#include "../tool/binary_buf.h"
#include "../tool/thread_safe_list.h"
#include "../tool/thread_condition.h"

#include "../communication/communication.pb.h"
#include "../communication/communication_message.h"

#include "../message/message_base.pb.h"
//#include "../message/measure_message.pb.h"



#define COMMUNICATION_PARAMETER_PATH "../setting/communication.prototxt"

class Communication_socket_base
{
	//通信状态
	enum Communication_statu
	{
		COMMUNICATION_UNKNOW		=0,	        //通信状态 未知
		COMMUNICATION_READY			=1,			//通信状态 正常

		COMMUNICATION_FAULT			=3,         //通信状态 错误
	};

public:
	Communication_socket_base();
	Communication_socket_base(const Communication_socket_base& other)= delete;
	Communication_socket_base& operator =(const Communication_socket_base& other)= delete;
	~Communication_socket_base();
public://API functions
	//初始化 通信 模块。如下三选一
	virtual Error_manager communication_init();
	//初始化 通信 模块。从文件读取
	Error_manager communication_init_from_protobuf(std::string prototxt_path);
	//初始化 通信 模块。从protobuf读取
	Error_manager communication_init_from_protobuf(Communication_proto::Communication_parameter_all& communication_parameter_all);

	//初始化
	virtual Error_manager communication_init(std::string bind_string, std::vector<std::string>& connect_string_vector);
	//bind
	virtual Error_manager communication_bind(std::string bind_string);
	//connect
	virtual Error_manager communication_connect(std::vector<std::string>& connect_string_vector);
	//connect
	virtual Error_manager communication_connect(std::string connect_string);
	//启动通信, run thread
	virtual Error_manager communication_run();

	//反初始化 通信 模块。
	virtual Error_manager communication_uninit();
	
	
public://get or set member variable
	void set_analysis_cycle_time(unsigned int analysis_cycle_time);
	void set_encapsulate_cycle_time(unsigned int encapsulate_cycle_time);

protected:
	//mp_receive_data_thread 接受线程执行函数，
	//receive_data_thread 内部线程负责接受消息
	void receive_data_thread();

	//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
	virtual Error_manager check_msg(Communication_message* p_msg);

	//mp_analysis_data_thread 解析线程执行函数，
	//analysis_data_thread 内部线程负责解析消息
	void analysis_data_thread();

	//遍历接受链表, 解析消息,
	Error_manager analysis_receive_list();

	//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
	virtual Error_manager check_executer(Communication_message* p_msg);

	//处理消息, 需要子类重载
	virtual Error_manager execute_msg(Communication_message* p_msg);

	//mp_send_data_thread 发送线程执行函数，
	//send_data_thread 内部线程负责发送消息
	void send_data_thread();

	//mp_encapsulate_data_thread 封装线程执行函数，
	//encapsulate_data_thread 内部线程负责封装消息
	void encapsulate_data_thread();

	//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
	virtual Error_manager encapsulate_send_data();

public:
	//封装消息, 需要子类重载
	virtual Error_manager encapsulate_msg(std::string message);
	//封装消息, 需要子类重载
	virtual Error_manager encapsulate_msg(Communication_message* p_msg);

protected://member variable

	//通用的网络编程接口, 默认使用总线模式, (网状结构)
	nnxx::socket 						m_socket { nnxx::SP, nnxx::BUS };
	std::mutex 							m_mutex;				//m_socket的锁

	//通信状态
	Communication_statu 				m_communication_statu;			//通信状态

	//接受模块,
	Thread_safe_list<Communication_message*>		m_receive_data_list; 			//接受的list容器
	std::thread*						mp_receive_data_thread;    		//接受的线程指针
	Thread_condition					m_receive_condition;			//接受的条件变量
	std::thread*						mp_analysis_data_thread;    	//解析的线程指针
	Thread_condition					m_analysis_data_condition;		//解析的条件变量
	unsigned int 						m_analysis_cycle_time;			//自动解析的时间周期

	//发送模块,
	Thread_safe_list<Communication_message*>		m_send_data_list;				//发送的list容器
	std::thread*						mp_send_data_thread;    		//发送的线程指针
	Thread_condition					m_send_data_condition;			//发送的条件变量
	std::thread*						mp_encapsulate_data_thread;    	//封装的线程指针
	Thread_condition					m_encapsulate_data_condition;	//封装的条件变量
	unsigned int 						m_encapsulate_cycle_time;		//自动封装的时间周期



private:

};
















#endif //__COMMUNICATION_SOCKET_BASE__HH__