/*
 * @Author: yct 18202736439@163.com
 * @Date: 2022-09-22 18:00:51
 * @LastEditors: yct 18202736439@163.com
 * @LastEditTime: 2022-09-25 22:10:59
 * @FilePath: /puai_wj_2021/wanji_lidar/wanji_716N_device.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <chrono>
#include <mutex>
#include <thread>
#include <atomic>
#include <string>
#include <unistd.h>
#include <glog/logging.h>

#include "async_client.h"
#include "wj_716N_lidar_protocol.h"

class Wanji_716N_lidar_device {
public:
    //万集设备身状态
    enum Wanji_716N_device_status {
        E_UNKNOWN = 0,      //未知
        E_READY = 1,        //正常待机
        E_DISCONNECT = 2,   //断连
        E_BUSY = 3,         //工作正忙
        E_FAULT = 10,       //故障
    };

public:
    Wanji_716N_lidar_device();
    ~Wanji_716N_lidar_device();

    // 初始化
    Error_manager init(std::string ip, int port,
                       Point2D_tool::Polar_coordinates_box t_polar_coordinates_box,
                       Point2D_tool::Point2D_box t_point2D_box,
                       Point2D_tool::Point2D_transform t_point2D_transform);

    //反初始化
    Error_manager uninit();

    //检查雷达状态,是否正常运行
    Error_manager check_status();

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

    //外部调用获取新的点云, 获取指令时间之后的点云, 如果没有就会等待点云刷新, 直到超时, (内置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_716N_device_status get_status();

protected:
    void updata_status();

protected:
    //状态
    Wanji_716N_device_status    m_wanji_lidar_device_status;    //万集设备身状态

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

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

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

};

