//
// Created by huli on 2022/12/30.
//

#ifndef NNXX_TESTS_NETWORK_BASE_H
#define NNXX_TESTS_NETWORK_BASE_H

#include <string>
#include <iostream>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include<netinet/tcp.h>

#include <map>
#include <mutex>
#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 "../network_communication/network_message.h"
#include "../network_communication/network.pb.h"




//网络通信的基类, linux C语言, 目前只有TCP client,
class Network_base
{
public:

#define NETKORK_PARAMETER_PATH "../setting/network.prototxt"
#define NETKORK_PARAMETER_PATH_A "../setting/network_a.prototxt"
#define NETKORK_PARAMETER_PATH_B "../setting/network_b.prototxt"
#define NETKORK_PARAMETER_PATH_C "../setting/network_c.prototxt"

#define NETKORK_CONNECT_TIME 	5		//连接时间, 单位秒
#define NETKORK_RECONNECT_OVER_TIME 	2		//重连超时判断的时间, 单位秒
#define NETWORK_BUFFER_SIZE		1024	//接受缓存, 每帧最多 1024 byte

	//通信状态
	enum Network_status
	{
		NETWORK_STATUS_UNKNOW = 0,            	//通信状态 未知
		NETWORK_STATUS_READY = 1,            	//通信状态 正常
		NETWORK_STATUS_DISCONNECT = 11,            	//通信状态 断连(可能会在断连和重连之间反复跳动)
		NETWORK_STATUS_RECONNNECT = 12,            	//通信状态 重连(可能会在断连和重连之间反复跳动)


		NETWORK_STATUS_FAULT = 100,         	//通信状态 错误
	};

////网络连接模式
//	enum Network_mode
//	{
//		NETWORK_UNKNOWN = 0;
//		TCP_CLIENT = 1;
//		TCP_SERVER = 2;
//		UDP = 3;
//	}
//
////单个网络连接参数
//	message Network_information
//	{
//		optional Network_mode               network_mode = 1[default = NETWORK_UNKNOWN];
//		optional int32                      socket_id = 2[default = 0];         //自定义的socket编号
//		optional string                     ip = 3[default = ""];
//		optional int32                      port = 4[default = 0];
//	}
	
	//网络连接的 socket
	struct Network_socket
	{
		Network_status						m_network_status;				//每一个连接的状态
	    int 								m_socket_fd;					//系统自动分配的编号 socket_fd

		Network_proto::Network_information	m_network_information;			//单个网络连接参数
		std::chrono::system_clock::time_point m_updata_time;				//通信更新时间
	};


	
public:
	Network_base();
	Network_base(const Network_base& other)= default;
	Network_base& operator =(const Network_base& other)= default;
	~Network_base();
public://API functions
	//初始化 通信 模块。如下三选一
	Error_manager network_init();
	//初始化 通信 模块。从文件读取
	Error_manager network_init_from_protobuf(std::string prototxt_path);
	//初始化 通信 模块。从protobuf读取
	Error_manager network_init_from_protobuf(Network_proto::Network_parameter_all & network_parameter_all);

	//启动通信, run thread
	Error_manager network_run();

	//反初始化 通信 模块。
	Error_manager network_uninit();
	//重连, 快速uninit, init
	Error_manager network_reconnnect();

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://member functions
	bool set_block(int socket_fd, bool isblock);  //设置阻塞模式  （希望只有在connect的时候是非阻塞的，而接收数据时候是阻塞的）
	int network_recv(int socket_fd, char *buf, int size);          //接收数据
	int network_send(int socket_fd, const char *buf, int size);	//发送数据
	bool is_connected(int socket_fd);//判断连接状态
	Error_manager check_and_reconnect(int socket_id);//检查网络,如果断连, 就立刻重连, socket_fd会重新分配新的

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

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

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

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

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

	//处理消息, 需要子类重载
	virtual Error_manager execute_msg(Network_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 auto_encapsulate_status();

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



protected://member variable

	Network_status								m_network_status;		//通信总状态

	Network_proto::Network_parameter_all		m_network_parameter_all;	//配置文件导入参数
	std::map<int, Network_socket>				m_network_socket_map; 	//网络连接配置, key是自定义的socket_id编号

	std::mutex 									m_mutex;		// 数据锁

	//接受模块,
	Thread_safe_list<Network_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<Network_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;		//自动封装的时间周期

	//回调函数,
	// //可以选择设置回调函数,或者子类继承重载,二选一.
	Error_manager (*check_msg_callback)(Network_message* p_msg);
	Error_manager (*check_executer_callback)(Network_message* p_msg);
	Error_manager (*execute_msg_callback)(Network_message* p_msg);
	Error_manager (*encapsulate_status_callback)();

private:

};


#endif //NNXX_TESTS_NETWORK_BASE_H
