//
// Created by zx on 2019/12/27.
//

#ifndef TERMINOR_H
#define TERMINOR_H

#include "../plc/plc_communicator.h"
#include "../plc/plc_task.h"
#include "../laser/Laser.h"
#include "../locate/locater.h"
#include "../verify/Verify_result.h"
#include "../wj_lidar/fence_controller.h"
#include "Terminor_parameter.pb.h"
#include <thread>
#include <mutex>
/*
 * 终端指令执行状态,枚举
 * 列举终端指令从进入流程到测量完成过程中的进度状态
 */
enum TerminorStatu
{
    TERMINOR_READY=0,           //终端空闲
    TERMINOR_BUSY,              //接收到指令/被占用
    TERMINOR_SCANNING,          //终端指令一启动扫描,扫描中
    TERMINOR_MEASURING,         //终端指令进入测量中
    TERMINOR_POSTING,           //终端测量完成, 正在上传数据
    TERMINOR_INVALID           //终端指令执行异常,当出现硬件故障,功能模块bug严重错误时,时为异常状态,
};

/*
 * 终端指令执行类,执行指令,监控指令执行进度
 * 输入雷达数组,plc对象,测量算法对象,执行扫描测量任务
 */
class Terminor_Command_Executor
{
public:
    /*
     * 构造函数
     * parameter:该终端指令配置参数(待定)
     */
    Terminor_Command_Executor(Terminal::Terminor_parameter parameter);
    ~Terminor_Command_Executor();
    /*
     * 获取终端进度状态
     */
    TerminorStatu get_terminor_statu();
    /*
     * 执行扫描,测量任务,阻塞知道任务完成或超时(单位秒)
     * 函数体只检测指令是否能执行,并启动线程执行指令,不等待指令完成.
     *lasers:需要启动的雷达
     * wj_lidar:万集雷达测量模块
     * plc:上传结果工具
     * locater:测量算法对象
     * verify_tool:结果检验工具,当该参数为NULL时,测量结果不作检验
     * 返回指令是否启动成功
     */
    Error_manager execute_command(std::vector<Laser_base*> lasers,Fence_controller* wj_lidar,
        Plc_Communicator* plc,
        Locater* locater,Verify_result* verify_tool,float timeout=15);
    /*
     * 强制正在执行的中断指令
     */
    Error_manager force_stop_command();
    /*
     * 设置保存文件的root路径
     * 执行指令时会在此路径下,生成日期文件夹,格式为:/root_path/year/month/day/YYYYMMDD-HHMMSS文件夹
     */
    void set_save_root_path(std::string root);
protected:

    static void thread_command_working(Terminor_Command_Executor* terminor);
    /*
     * 执行指令流程函数
     * 扫描
     * 测量,保存测量结果到成员变量
     */
    Error_manager scanning_measuring();
    /*
     * 执行上传plc任务
     * plc终端编号从1开始
     */
    Error_manager post_measure_information();
    /*
     * 根据长宽,角度,生成cv::RotateRect
     */
    static cv::RotatedRect create_rotate_rect(float length,float width,float angle,float x,float y);
protected:
    TerminorStatu               m_terminor_statu;
    //指令流程线程
    std::thread*                mp_command_thread;
    //
    std::mutex                  m_mutex_lock;
    //保存输入进来的雷达指针
    std::vector<Laser_base*>    mp_laser_vector;
    //万集雷达测量模块
    Fence_controller*           mp_wj_lidar;
    //plc
    Plc_Communicator*           mp_plc;
    //locater*
    Locater*                    mp_locater;
    //配置参数
    Terminal::Terminor_parameter    m_terminor_parameter;
    //本次指令超时时间 单位秒
    float                       m_timeout_second;
    //强制退出标示
    bool                        mb_force_quit;
    //保存当前指令测量结果
    Locate_information          m_measure_information;
    //保存文件的root目录
    std::string                 m_save_root_path;
    //检验结果工具
    Verify_result*              mp_verify_tool;

    //
    static std::mutex                  ms_mutex_scan_measure;

};

#endif //TERMINOR_H
