#ifndef CMT_PROTOCOL_HPP_
#define CMT_PROTOCOL_HPP_
#include <iostream>
#include <boost/asio.hpp>
#include <cstdlib>
#include <memory>
#include <utility>
#include <unordered_set>

using boost::asio::ip::tcp;

#define CMT_TCP_LEN 100000 

//1 tcp server可以参考本安有线中的代码，侦听端口10000
//2 定义无线网关与传感器用到的结构
//3 包头为 

#pragma pack(1)  
struct PackageHead{
	uint8_t head[3]; // 固定值：0xAA55AA
	uint8_t cmd;
	int		len;
	char 	data[0];
};

//网关版本和状态信息cmd 80 
struct GatewayVersion{
	int     version;  // 写1
	char 	web_ver[12];
	char 	system_ver[12];
	char 	gateway_ver[12];
	char 	ip[16];
	char 	gateway_type[12];
	char 	gateway_hw_ver[12];
	char 	terminal_name[32]; // 终端名称，如果为空，填写Default
	int 	cpu_use;
	int 	memory_use;
	int 	disk_remain;
	int 	temperature;
	char 	comm_mode[10];
	char	mac[20];
};
enum SensorStatus{
	OFFLINE = 0,
	ONLINE 	= 1
};
enum SensorUpgradeStatus{
	UPGRADE_NORMAL  = 0,
	UPGRADING 		= 1,
	UPGRADE_SUCCESS = 2,
	UPGRADE_FALIED 	= 3
};
enum LooseStatus{
	NORMAL 	= 0,
	LOOSE 	= 1
};
//传感器信息cmd 81

struct SensorInfoReq{
	char 	short_addr[4];
};
struct SensorInfo{
	int     version;
	char	sensor_name[64];
	char 	measurement_id[20];
	char 	short_addr[5];
	char 	hw_ver[12];
	char 	soft_ver[12];
	int 	gateway_rssi;
	int 	sensor_rssi;
	int 	battry;
	int 	loose_status;	//参考 LooseStatus
	int 	temperature_bot;
	int 	temperature_top;
	char 	product[6];		// DN101；DN102
	int  	status;   		// 参考 SensorStatus
	int 	eigen_value_reporting_rate;
	int 	wave_x_reporting_rate;
	int 	wave_y_reporting_rate;
	int 	wave_z_reporting_rate;
	float	velocity_rms;
	int 	upgrade_status; // 参考 SensorUpgradeStatus
	char	upgrade_time[20];
};

enum ChannelType{
	X = 1,
	Y = 2,
	Z = 3
};
//波形cmd 82
struct WaveReq{
	char 	measurement_id[20];
	int		channel;//参考 ChannelType
};

struct WaveRes{
	int     version;
  	int 	sampling_rate;
	int 	sampling_time;
	char 	wave[0];
};

//下载配置 cmd 83 
struct DownloadConfigReq{
	char 	measurement_id[20];
};
enum Range{
	RANGE_8G = 0,
	RANGE_16G = 1,
	RANGE_32G = 2,
	RANGE_64G = 3,
	RANGE_50G = 4
};
struct DownloadConfigRes{
	int     version;
	char	filename[128];
};
struct DownloadConfig{
	char 	gw_mac[20];
	char 	product[6];			// DN101；DN102
	char	ip[16];
	int		panid;
	int 	signal_channle;
	char	terminal_name[32];
	char	sn[10];
	char	sensor_mac[20];
	char	measurement_id[20];
	int     short_addr;
	char    sensor_name[64];
	char    update_date[20];
	int     gateway_rssi;
	int     sensor_rssi;
	char 	hw_ver[12];
	char 	soft_ver[12];
	int     sampling_rate;
	int     range;				//量程 参考 Range
	int     sampling_time;
	int     viff;				//速度积分起始频率
	int     power;				//zigbee发射功率
	int     retry_time;			//zigbee重发次数
};

//上传配置 cmd 84
struct UploadConfigReq{
	char	filename[64];
	char	md5[33];
};
struct UploadConfigRes{
	int     version;
	int		code;
	char	message[64];
};
//网关更新 cmd 85
struct UpgradeGwReq{
	char	filename[64];
	char	md5[33];
};

struct UpgradeGwRes{
	int     version;
	int		code;
	char	message[64];
};
//传感器更新 cmd 86
struct UpgradeSensorReq{
	char	filename[64];
	char	md5[33];
	char 	upgrade_short_addr[0];
};
struct UpgradeSensorRes{
	int     version;
	int		code;
	char	message[64];
};
//获取特征值 cmd 87
struct GetEigenvalueReq{
	char 	measurement_id[20];
};
struct GetEigenvalueRes{
	int   version;
	int	  channel;//参考 ChannelType
	float DiagnosisPk;
    float IntegratPk;
    float IntegratRMS;
    float RmsValues;
    float EnvelopEnergy;
    float Amp1;
    float Amp2;
    float Amp3;
    float Amp4;
    float Amp5;
    float Phase1;
    float Phase2;
    float Phase3;
    float Phase4;
	int   Time;
};

//停止更新传感器 cmd 88
struct UpgradeStopReq{
	int 	short_addr;
};
struct UpgradeStopRes{
	int     version;
	int		code;
	char	message[64];
};
// 搜索应答 cmd 1
struct Search {
	int     version;
	char 	mac[20];
	int     gw_type; // GatewayType
};

class CMTSession : public std::enable_shared_from_this<CMTSession> {
public:
    CMTSession(tcp::socket socket, std::unordered_set<std::shared_ptr<CMTSession>>& sessionSet) : socket_(std::move(socket)), sessionSet_(sessionSet) {
        web_version_ = "1.0.1";
        version_ = 1;
        head_len_ = sizeof(PackageHead);
    }
   ~CMTSession() {
	if (data_ != nullptr) {
		free(data_);
	}
    }

    void start();
    void set_data(char *data, int len);
    void do_write(std::size_t length); 

private:
    void do_read();       

    tcp::socket socket_;
    std::unordered_set<std::shared_ptr<CMTSession>>& sessionSet_;
    char *data_;
    std::string web_version_;
    int version_;
    int head_len_;
};

class CMTServer {
public:
    CMTServer(boost::asio::io_service& io_service, short port) : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), socket_(io_service) { do_accept(); }

    // 向所有客户端发送消息
    void send_message_to_all(char *message, int len) {
        for (auto& session : sessionSet_) {
            session->set_data(message, len);
            session->do_write(len);
        }
    }
private:
    void do_accept();

    tcp::acceptor acceptor_;
    tcp::socket socket_;
    std::unordered_set<std::shared_ptr<CMTSession>> sessionSet_;
};

#endif
