//
// Created by zx on 2019/12/6.
//
#ifndef FENCECONTROLLER_H
#define FENCECONTROLLER_H

#include <iostream>
#include <string>
#include <fstream>
#include <string.h>
#include <thread>
#include <unistd.h>
#include <atomic>
#include "string.h"

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
using google::protobuf::Message;
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;
using google::protobuf::io::ZeroCopyInputStream;
using google::protobuf::io::ZeroCopyOutputStream;

#include "glog/logging.h"

#include "wj_lidar_conf.pb.h"
#include "wj_lidar_encapsulation.h"
#include "region_worker.h"
#include "plc_data.h"
#include "../tool/pathcreator.h"
#include "../tool/threadSafeQueue.h"
#include "../verify/Verify_result.h"
#include "../error_code/error_code.h"
#include "wj_lidar_task.h"

#include <nnxx/message.h>
#include <nnxx/message_control.h>
#include <nnxx/socket.h>
#include <nnxx/reqrep.h>
//#include <nnxx/unittest.h>
#include <nnxx/timeout.h>
#include <nnxx/error.h>
#include <cstring>
#include <nnxx/message>

#define CONNECTSTRING "tcp://127.0.0.1:9000"

// 轮距计算任务结构体，监听到任务后生成该对象存入数组等待处理
typedef struct MSGTASK
{
    std::string cmd;
    nnxx::message_control *sock_controller;
} MsgTask;

/**
 * 电子围栏/万集雷达管理类，
 * 负责管理雷达数组用于获取点云，管理区域功能数组用于检测区域状态，并将区域状态实时更新到plc
 * */
class Fence_controller
{
public:
    // 有参构造函数
    Fence_controller(Verify_result* verify_handle);
    // 析构函数
    ~Fence_controller();
    // 初始化函数
    Error_manager initialize(wj::wjManagerParams params);
    // 获取当前整体状态函数
    Error_manager get_current_status();
    // 外部获取点云
    Error_manager get_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out);
    // 获取初始化状态
    bool get_initialize_status();
    // 接收任务单进行阻塞式处理
    Error_manager execute_task(Task_Base* task);

private:
    // 点云拼接线程函数
    static void cloud_merge_update(Fence_controller *fc);
    // 轮距指令接收线程函数，监听计算轮距消息
    static void wheel_msg_recv_thread(Fence_controller *fc);
    // 轮距消息处理线程函数，计算并反馈轮距结果
    static void wheel_msg_handling_thread(Fence_controller *fc);
    // // 测量功能函数
    // Error_manager wj_fence_measure();

    // 工具函数，根据路径读取配置参数，暂未使用
    bool read_proto_param(std::string path);
    // 工具函数，保存点云到文件
    void save_cloud_txt(std::string txt, pcl::PointCloud<pcl::PointXYZ>::Ptr pCloud);

private:
    wj::wjManagerParams m_wj_manager_param; // 万集管理器配置参数
    std::atomic<bool> mb_initialized;       // 系统初始化状态

    std::mutex m_cloud_mutex;                            // 点云更新互斥锁
    pcl::PointCloud<pcl::PointXYZ>::Ptr mp_merged_cloud; // 拼接后点云

    std::vector<Wj_lidar_encapsulation *> m_lidars_vector; // 万集雷达实例指针数组
    std::vector<Region_worker *> m_region_workers_vector;  // 区域功能实例指针数组
    Plc_data *mp_plc_data;                                 // plc 句柄

    nnxx::socket m_wheel_soc{nnxx::SP_RAW, nnxx::REP}; // nnxx轮距计算任务监听与反馈socket句柄
    std::mutex m_mutex_wheel_handling;                 // 轮距计算任务处理互斥锁
    static int S_RETRY_TIMES;                       // 计算失败后重试次数

    StdCondition m_cond_exit;     // 更新线程退出标记
    std::thread *m_update_thread; // 更新线程

    std::thread *m_wheel_recv_thread;      // 轮距计算任务监听线程
    std::thread *m_wheel_send_thread;      // 轮距计算结果发送线程
    StdCondition m_cond_wheel_exit;        // 轮距计算线程退出标记
    threadsafe_queue<MsgTask> m_msg_queue; // 轮距计算任务队列

    Verify_result* mp_verify_result_tool; //结果检验工具
};

#endif //FENCECONTROLLER_H
