#ifndef __LIVOX_MID_40_LIDAR__H
#define __LIVOX_MID_40_LIDAR__H
#include "Laser.h"
#include "livox_def.h"
#include "livox_sdk.h"
#include <map>

//大疆livox雷达，从Laser_base继承。
class CLivoxLaser :public Laser_base
{
protected:
	//雷达设备状态，livox管理底层sdk，后台线程的工作状态
	typedef enum
	{
		kDeviceStateDisconnect = 0,		//雷达设备状态	断开连接
		kDeviceStateConnect = 1,		//雷达设备状态	连接正常
		kDeviceStateSampling = 2,		//雷达设备状态	正在扫描
	} DeviceState;

	//雷达设备信息，
	typedef struct
	{
		uint8_t handle;					//雷达控制句柄
		DeviceState device_state;		//雷达设备状态
		DeviceInfo info;				//雷达基本信息
	} DeviceItem;


public:
	CLivoxLaser() = delete;
	CLivoxLaser(const CLivoxLaser& other) = delete;
	//唯一的构造函数，按照设备名称和雷达参数来创建实例。
	//input：id： 雷达设备的id，（唯一索引）
	//input：laser_param：雷达的参数，
	//注：利用protobuf创建 laser_parameter 类，然后从文件读取参数
	CLivoxLaser(int id, Laser_proto::laser_parameter laser_param);
	~CLivoxLaser();

	//雷达链接设备，为3个线程添加线程执行函数。
	virtual Error_manager connect_laser();
	//雷达断开链接，释放3个线程
	virtual Error_manager disconnect_laser();
	//对外的接口函数，负责接受并处理任务单，
	//input：p_laser_task 雷达任务单，基类的指针，指向子类的实例，（多态）
	//注：这个函数为虚函数，实际的处理任务的代码由子类重载并实现。
	virtual Error_manager execute_task(Task_Base* p_laser_task);
	//检查雷达状态,是否正常运行
	virtual Error_manager check_laser();
	//雷达的启动接口函数， 让雷达进行扫描，一般需要子类重载，不同的雷达开始方式不同。
	virtual Error_manager start_scan();
	//雷达的停止接口函数， 让雷达停止扫描，一般需要子类重载，不同的雷达结束方式不同。
	virtual Error_manager stop_scan();
	//结束任务单，stop之后，要检查线程状态和数据结果，然后才能 end_task
	virtual Error_manager end_task();

	//判断雷达状态是否为待机，如果已经准备好，则可以执行任务。
	//子类重载 is_ready()，里面增加livox sdk后台线程状态的判断。
	virtual bool is_ready();

protected:
	//接受二进制消息的功能函数，每次只接受一个CBinaryData
	// 纯虚函数，必须由子类重载，
	virtual bool receive_buf_to_queue(Binary_buf& binary_buf);
	//将二进制消息转化为三维点云的功能函数，每次只转化一个CBinaryData，
	// 纯虚函数，必须由子类重载，
	virtual Buf_type transform_buf_to_points(Binary_buf* p_binary_buf, std::vector<CPoint3D>& point3D_cloud);



protected:
	static void InitLivox();
	virtual bool IsScanComplete();
	virtual void UpdataHandle();
	static void LidarDataCallback(uint8_t handle, LivoxEthPacket *data, uint32_t data_num, void *laser);
	static void OnDeviceChange(const DeviceInfo *info, DeviceEvent type);
	static void OnDeviceBroadcast(const BroadcastDeviceInfo *info);
	static void OnSampleCallback(livox_status status, uint8_t handle, uint8_t response, void *data);

protected:
	uint8_t									m_handle;
	unsigned int							m_frame_maxnum;
	Thread_safe_queue<Binary_buf*>			m_queue_livox_data;

	static DeviceItem						g_devices[kMaxLidarCount];
	
	static std::map<uint8_t,std::string>	g_handle_sn;
	static std::map<std::string, uint8_t>	g_sn_handle;
	static std::map<std::string, CLivoxLaser*> g_sn_laser;
	static CLivoxLaser*						g_all_laser[kMaxLidarCount];
	static unsigned int						g_count[kMaxLidarCount];


};

#endif

