//
// Created by huli on 2021/11/18.
//

#ifndef NNXX_TESTS_DISPATCH_SINGLECHIP_H
#define NNXX_TESTS_DISPATCH_SINGLECHIP_H

#include "../error_code/error_code.h"
#include <glog/logging.h>
#include <thread>
#include <mutex>
#include "../tool/thread_condition.h"
#include "../tool/common_data.h"
#include "../tool/time_tool.h"
#include "../task/task_base.h"
//#include "../message/dispatch_message.pb.h"
#include "../message/singlechip_msg.pb.h"
#include "../message/message.pb.h"
#include "../dispatch/dispatch_communication.h"
#include <google/protobuf/message.h>
#include <google/protobuf/util/json_util.h>
#include <google/protobuf/text_format.h>

//调度单片机通信
class Dispatch_singlechip
{
public:
	//调度plc状态
	enum Dispatch_singlechip_status
	{
		DISPATCH_SINGLECHIP_UNKNOW               	= 0,    //未知
		DISPATCH_SINGLECHIP_READY               	= 1,    //准备，待机

		DISPATCH_SINGLECHIP_FAULT					= 10,	//故障
		DISPATCH_SINGLECHIP_DISCONNECT			= 11, 	//断连

	};
public:
	Dispatch_singlechip();
	Dispatch_singlechip(const Dispatch_singlechip& other)= default;
	Dispatch_singlechip& operator =(const Dispatch_singlechip& other)= default;
	~Dispatch_singlechip();
public://API functions
	//调度单片机 初始化,  单片机id, 0或者1, 单片机方向, 1是入口, 2是出口
	Error_manager dispatch_singlechip_init(int plc_id, int singlechip_id, int singlechip_direction);
	//调度单片机 反初始化
	Error_manager dispatch_singlechip_uninit();
	//调度单片机 执行状态消息
//	Error_manager execute_for_singlechip_data_msg(message::Singlechip_data &singlechip_data_msg, bool validity);
	//调度单片机 执行状态消息
	Error_manager execute_for_singlechip_data_msg_new(in_mcpu_statu &t_in_mcpu_statu, bool validity);
	//调度单片机 执行状态消息
	Error_manager execute_for_singlechip_data_msg_new(out_mcpu_statu &t_out_mcpu_statu, bool validity);

	//单片机消息, 数据处理, 去头,去尾 //删除头部 @501, 删除尾部 $,
	Error_manager data_processing(std::string & put_in, std::string & put_out);
	//调度单片机 执行状态消息, 单片机通过tcp发过来的原始字符串
	Error_manager execute_for_singlechip_data_msg_new(std::string singlechip_data);


	//判断出口是否空闲, 没有车就是空闲, 返回true
	bool is_outlet_ready();
	//判断入口是否空闲, 没有车就是空闲, 返回true
	bool is_inlet_ready();


public://get or set member variable
	Dispatch_singlechip_status get_dispatch_singlechip_status();

	//获取外门状态, 0表示未知, 1表示外门开到位, 2表示外门关到位, 3表示外门运行中 4表示外门故障
	message::Outside_door_status get_outside_door_status();
	//获取内部是否有车, 0表示无车, 1表示有车. -1表示未知
	int get_inside_existence_flag();

protected://member functions
	//任务执行线程, 负责门控和数据库操作
	void execute_thread_fun();
	//入口外门控制函数
	Error_manager inlet_outsidedoor_control();
	//出口外门控制函数
	Error_manager outlet_outsidedoor_control();

	//发送开门指令
	Error_manager open_outside_door();
	//发送关门指令
	Error_manager close_outside_door();

	//任务执行线程, 负责数据管理, 和通信转化, tcp rabbitmq snap7
	void updata_thread_fun();
	//数据同步更新, tcp->rabbitmq, tcp->snap7
	void updata_singlechip_data();
protected://member variable
	std::atomic<Dispatch_singlechip_status>				m_dispatch_singlechip_status;//调度单片机的状态


	int 										m_plc_id;					//设备id, 索引, 就是楚天车库的单元号.
	int 										m_singlechip_id;			//单片机id, 0或者1
	int 										m_singlechip_direction;		//单片机方向, 1是入口, 2是出口
	std::mutex									m_lock;	//锁

	//任务执行线程, 负责门控和数据库操作
	std::thread*        						mp_execute_thread;   			//执行的线程指针，内存由本类管理
	Thread_condition							m_execute_condition;			//执行的条件变量
	//任务执行线程, 负责数据管理, 和通信转化, tcp rabbitmq snap7
	std::thread*        						mp_updata_thread;   			//数据更新的线程指针，内存由本类管理
	Thread_condition							m_updata_condition;				//数据更新的条件变量


	//数据缓存
	message::Singlechip_data 						m_singlechip_data_msg;		//单片机的数据, proto格式, 直连单片机tcp
	in_mcpu_statu 									m_in_mcpu_statu;		//新版入口单片机消息
	out_mcpu_statu 									m_out_mcpu_statu;		//新版出口单片机消息
	bool 											m_validity;					//有效性

	std::chrono::system_clock::time_point			m_singlechip_data_msg_updata_time;	//状态更新时间点
	std::atomic<bool>								m_singlechip_data_msg_updata_flag;

	std::string										m_primary_key_last;//入口存车流程的唯一码
	bool 											m_close_outsidedoor_flag;//入口外门关闭标志位

private:

};


#endif //NNXX_TESTS_DISPATCH_SINGLECHIP_H
