#ifndef WJ_LIDAR_ENCAPSULATION_HH
#define WJ_LIDAR_ENCAPSULATION_HH

#include "async_client.h"
#include "wj_716_lidar_protocol.h"
#include "error_code/error_code.hpp"
#include "tool/binary_buf.h"
#include "tool/thread_safe_queue.hpp"
#include "wanji_lidar_scan_task.h"

class Wanji_lidar_device
{
public:
	//万集设备身状态
	enum Wanji_lidar_device_status
	{
		E_UNKNOWN              	= 0,    //未知
		E_READY	             	= 1,    //正常待机
		E_DISCONNECT			= 2,	//断连

		E_BUSY					= 3, 	//工作正忙

		E_FAULT					=10,	//故障
	};

public:
    // 无参构造函数
    Wanji_lidar_device();
    // 析构函数
    ~Wanji_lidar_device();

	// 初始化
	Error_manager init(wj::wjLidarParams params);
	//反初始化
	Error_manager uninit();

	//对外的接口函数，负责接受并处理任务单，
	Error_manager execute_task(Task_Base* p_wanji_lidar_scan_task);

	//检查雷达状态,是否正常运行
	Error_manager check_status();
	//结束任务单，里面会根据任务的故障等级修正雷达管理模块的状态和任务单的状态
	Error_manager end_task();
	//取消任务单，由发送方提前取消任务单
	Error_manager cancel_task(Task_Base* p_wanji_lidar_scan_task);

	//判断是否为待机，如果已经准备好，则可以执行任务。
	bool is_ready();

	int get_lidar_id() { return m_lidar_id; }

	//外部调用获取新的点云, 获取指令时间之后的点云, 如果没有就会等待点云刷新, 直到超时, (内置while)
	Error_manager get_new_cloud_and_wait(std::mutex* p_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
							std::chrono::system_clock::time_point command_time, int timeout_ms=1500);

	//外部调用获取当前点云, 获取指令时间之后的点云, 如果没有就会报错, 不会等待
	Error_manager get_current_cloud(std::mutex* p_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
									std::chrono::system_clock::time_point command_time);
	//外部调用获取最新的点云, 获取指令时间往前一个周期内的点云, 如果没有就会报错, 不会等待
	Error_manager get_last_cloud(std::mutex* p_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
							std::chrono::system_clock::time_point command_time);

	//外部调用获取最新的点云, 获取指令时间往前一个周期内的点云, 如果没有就会报错, 不会等待
	//注:函数内部不加锁, 由外部统一加锁.
	Error_manager get_last_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud,
								 std::chrono::system_clock::time_point command_time);
public:
	Wanji_lidar_device_status get_status();
protected:
	void updata_status();
	//mp_laser_manager_thread 线程执行函数，
	//thread_work 内部线程负责获取点云结果
	void execute_thread_fun();



protected:
	// 雷达编号
	int m_lidar_id;

	//状态
	Wanji_lidar_device_status 					m_wanji_lidar_device_status;	//万集设备身状态

	//子模块
	Async_Client								m_async_client;		//异步客户端, 负责雷达通信, 接受雷达数据
	Wj_716_lidar_protocol						m_protocol;        // 万集雷达协议

	//中间缓存
	Thread_safe_queue<Binary_buf*>				m_communication_data_queue;	//通信数据队列


	//任务执行线程
	std::thread*        						mp_execute_thread;   			//执行的线程指针，内存由本类管理
	Thread_condition							m_execute_condition;			//执行的条件变量

	Wanji_lidar_scan_task *  					mp_wanji_lidar_scan_task;   //雷达设备任务单的指针，内存由发送方管理。

};

#endif // !WJ_LIDAR_ENCAPSULATION_HH