//
// Created by huli on 2020/7/20.
//

#ifndef NNXX_TESTS_DISPATCH_MANAGER_H
#define NNXX_TESTS_DISPATCH_MANAGER_H


#include "../error_code/error_code.h"
#include "../communication/communication_message.h"
#include "../system/system_communication.h"
#include "../dispatch/dispatch_network.h"

#include "../tool/singleton.h"
#include "../tool/thread_condition.h"
#include "../tool/TaskQueue/TQFactory.h"
#include "../tool/TaskQueue/BaseTask.h"

//#include "../dispatch/carrier.h"
//#include "../dispatch/catcher.h"
//#include "../dispatch/passageway.h"
//#include "../dispatch/dispatch_process.h"

//#include "../message/dispatch_control.pb.h"
//#include "../message/dispatch_message.pb.h"
#include "../dispatch/dispatch_parameter.pb.h"
#include "../dispatch/dispatch_plc.h"
#include "../dispatch/dispatch_command.h"

#ifdef CHUTIAN_PROJECT_PROJECT
#include "../dispatch/dispatch_ground_lidar.h"
#include "../dispatch/dispatch_singlechip.h"
#endif //CHUTIAN_PROJECT_PROJECT

#include "../dispatch/dispatch_ground_lidar.h"


//#include "../message/measure_message.pb.h"
#include "../message/message.pb.h"


#include <vector>
#include <glog/logging.h>
#include <atomic>


//lacate测量结果结构体, 整车的信息,
typedef struct Locate_information
{
	float locate_x;				//整车的中心点x值, 四轮的中心
	float locate_y;				//整车的中心点y值, 四轮的中心
	float locate_angle;			//整车的旋转角, 四轮的旋转角
	float locate_length;		//整车的长度, 用于规避碰撞
	float locate_width;			//整车的宽度, 用于规避碰撞
	float locate_height;		//整车的高度, 用于规避碰撞
	float locate_wheel_base;	//整车的轮距, 前后轮的距离, 用于机器人或agv的抓车
	float locate_wheel_width;	//整车的轮距, 左右轮的距离, 用于机器人或agv的抓车
	bool locate_correct;		//整车的校准标记位
	//注:理论上, 车宽和左右轮距应该是一样的, 但是实际上车宽比左右轮距略大,
}Locate_information;

//调度管理模块
class Dispatch_manager:public Singleton<Dispatch_manager>
{
// 子类必须把父类设定为友元函数，这样父类才能使用子类的私有构造函数。
	friend class Singleton<Dispatch_manager>;

public:
//调度设备参数
#define DISPATCH_DEVICE_PARAMETER_PATH "dispatch_device.prototxt"
//存车任务数量的限制, 大于等于限则, 则使用缓存位, 默认5个
#define DISPATCH_MANAHER_STORE_LIST_SIZE_LIMIT		5


	//调度管理 的状态
	enum Dispatch_manager_status
	{
		E_DISPATCH_MANAGER_UNKNOW               = 0,    //未知
		E_DISPATCH_MANAGER_READY                = 1,    //准备，待机

		E_DISPATCH_MANAGER_BUSY					= 2, 	//工作正忙
		E_DISPATCH_MANAGER_DISCONNECT			= 3, 	//断连

		E_DISPATCH_MANAGER_REQUEST				= 4, 	//给plc发送请求
		E_DISPATCH_MANAGER_WORKING				= 5, 	//plc工作中
		E_DISPATCH_MANAGER_REALLOCATE			= 6, 	//重新分配车位
		E_DISPATCH_MANAGER_RESPONSE				= 7, 	//给主控答复

		E_DISPATCH_MANAGER_STORE                = 8,    //正在存车
		E_DISPATCH_MANAGER_PICKUP               = 9,    //正在取车


		//新版
		E_DISPATCH_MANAGER_COUNT_NEW			= 11,    //第一步, 接受排序模块的计数, (当数据库有指令时,排序模块会给调度发一个排队总数)
		E_DISPATCH_MANAGER_REQUEST_NEW 			= 12,    //第二步, 发送调度任务申请,(当调度模块空闲时,向排序模块发送调度任务申请)
		E_DISPATCH_MANAGER_POST_NEW   			= 13,    //第三不, 接受调度指令(具体的存车取车任务)
		E_DISPATCH_MANAGER_COMPLETED_NEW 		= 14,    //第四步, 答复调度指令(具体的存车取车任务)

		E_DISPATCH_MANAGER_FAULT               = 100,  //故障
	};

	//调度方向, 停车取车
//	enum Dispatch_motion_direction
//	{
//		E_STORE_CAR             =0,         //停车, 出入口 -> 停车位
//		E_PICKUP_CAR            =1,         //取车, 停车位 -> 出入口
//	};


private:
	// 父类的构造函数必须保护，子类的构造函数必须私有。
	Dispatch_manager();
public:
	//必须关闭拷贝构造和赋值构造，只能通过 get_instance 函数来进行操作唯一的实例。
	Dispatch_manager(const Dispatch_manager& other) = delete;
	Dispatch_manager& operator =(const Dispatch_manager& other) = delete;
	~Dispatch_manager();
public://API functions
	//调度管理 初始化
	Error_manager dispatch_manager_init(int dispatch_manager_id);
	Error_manager dispatch_manager_init();
	//初始化 调度管理 模块。从文件读取
	Error_manager dispatch_manager_init_from_protobuf(std::string prototxt_path);
	//初始化 调度管理 模块。从protobuf读取
	Error_manager dispatch_manager_init_from_protobuf(Dispatch_proto::Dispatch_device_parameter_all& dispatch_device_parameter_all);
	//调度管理 反初始化
	Error_manager dispatch_manager_uninit();

	//调度管理 设备复位
	Error_manager dispatch_manager_device_reset();

	//新的对外接口, 负责接受Rabbitmq_message,然后内部处理
	Error_manager execute_rabbitmq_message_new(Rabbitmq_message* p_msg);
	//给dispatch_plc底层提供接口, ack答复服务器,
	Error_manager ack_rabbitmq_message_new();

	//网络通信的对外接口. 对单片机通信
	Error_manager execute_network_message_new(Network_message* p_msg);


	//对外的接口函数，负责接受并处理任务单，
//	Error_manager execute_task(Dispatch_manager::Dispatch_motion_direction dispatch_motion_direction);

	//检查能否执行消息指令
	Error_manager check_execute_msg(Rabbitmq_message* p_msg);
	//检查状态
	Error_manager check_status();

	//调度模块 //执行搬运请求(主控->调度管理)
//	Error_manager execute_for_dispatch_request_msg(message::Dispatch_request_msg &dispatch_request_msg);
//	//调度模块 答复数据异常
//	Error_manager send_dispatch_response_msg_with_error(message::Dispatch_request_msg &dispatch_request_msg, Error_manager error);
//
//	//调度模块 //调度总规划的答复(调度算法->调度管理)
//	Error_manager execute_for_dispatch_plan_response_msg(message::Dispatch_plan_response_msg &dispatch_plan_response_msg);
//	//调度模块 //调度控制的任务请求(调度算法->调度管理)
//	Error_manager execute_for_dispatch_control_request_msg(message::Dispatch_control_request_msg &dispatch_control_request_msg);
	//定时发送 调度管理的状态
	Error_manager encapsulate_send_dispatch_manager_status();
	//定时发送 调度管理的状态
	Error_manager encapsulate_send_dispatch_manager_status_new();

	//在流程的map 里面释放指定的流程
	Error_manager release_dispatch_process(std::string command_key);

	//调度模块 ///地面雷达的状态消息(地面雷达->null)
//	Error_manager execute_for_ground_status_msg(message::Ground_status_msg ground_status_msg);
	//调度模块 ///单片机的状态消息
//	Error_manager execute_for_singlechip_data_msg(message::Singlechip_data singlechip_data_msg, bool validity);

	//获取空闲的出口,返回0表示没有空闲出口, 返回1~6表示对应的出口
	int get_outlet_for_ready();

public://get or set member variable
	Dispatch_manager_status get_dispatch_manager_status();
	int get_dispatch_manager_id();
	void set_dispatch_manager_id(int dispatch_id);

protected:
	//资源分配
//	void resource_allocation();

	//新版流程控制
//	void process_control();

#ifdef CHUTIAN_PROJECT_PROJECT
	//新版流程控制
	void process_sql();
#endif//CHUTIAN_PROJECT_PROJECT

#ifdef SHANGGUJIE_PROJECT_PROJECT
	//新版流程控制
	void process_sql_shanggujie();
#endif//SHANGGUJIE_PROJECT_PROJECT

public://member variable

	Dispatch_manager_status						m_dispatch_manager_status;			//调度管理 的状态
	Dispatch_manager_status						m_dispatch_manager_status_last;				//上一次的存取车动作
	bool 										m_dispatch_manager_force_pickup_flag;		//强制取车标志。

	int 										m_dispatch_manager_id;						//调度模块的id, (楚天项目就是单元号, 0~2)

	//流程控制
	std::mutex                              	m_lock;        						//线程池的锁, 增删流程时要加锁.


	//调度plc
	Dispatch_plc								m_dispatch_plc;						//调度plc
	int 										m_plc_floor;						//穿梭机所在的楼层, 存车完在对应的车位楼层, 取车完在1楼

	Dispatch_ground_lidar						m_dispatch_ground_lidar[2];			//调度地面雷达


#ifdef CHUTIAN_PROJECT_PROJECT
	Dispatch_singlechip							m_dispatch_singlechip[4];			//调度单片机
#endif //CHUTIAN_PROJECT_PROJECT

	//请求指令的list, 按照创建顺序排序, 先来后到, 停车和停车不能插队, 但是停车和取车可以插队.
//	std::list<message::Dispatch_request_msg>				m_dispatch_request_store_list;					//存车请求指令的list, 内存由线程池管理
//	std::list<message::Dispatch_request_msg>				m_dispatch_request_pickup_list;					//取车请求指令的list, 内存由线程池管理
//	Common_data::Dispatch_motion_direction					m_dispatch_motion_direction_next;				//下一次的调度方向, 保证存车取车交替进行


//	std::map<std::chrono::system_clock::time_point , message::Dispatch_response_msg>
//															m_dispatch_response_store_map;					//存车dafu de map, 内存由线程池管理, time_point
//	std::map<int , message::Dispatch_response_msg>			m_dispatch_response_pickup_map;					//取车dafu de map, 内存由线程池管理, int:outlet_id
//	std::chrono::system_clock::time_point					m_store_updata_time;									//
//	std::chrono::system_clock::time_point					m_pickup_updata_time;									//

	//调度总管理的线程, 负责资源分配
	std::thread*                        		m_dispatch_manager_thread;        	//调度总管理的线程, 总控全局, 控制每个流程的先后顺序, 并合理的分配资源.
	Thread_condition				    		m_dispatch_manager_condition;		//调度总管理的条件变量, 总控全局, 控制每个流程的先后顺序, 并合理的分配资源.

	//新版调度,消息缓存
	int 										m_device_floor;	//设别楼层, 初始化为0
	bool 										m_count_flag;						//接受排序模块的计数 的标志位,
	Rabbitmq_message							m_count_command_signal_msg;			//第一步, 接受排序模块的计数, (当数据库有指令时,排序模块会给调度发一个排队总数)
	Rabbitmq_message							m_request_command_msg;				//第二步, 发送调度任务申请,(当调度模块空闲时,向排序模块发送调度任务申请)
	bool 										m_post_flag;						//接受调度指令 的标志位,
	Rabbitmq_message							m_post_command_msg;					//第三不, 接受调度指令(具体的存车取车任务)
	Rabbitmq_message							m_command_completed_msg;			//第四步, 答复调度指令(具体的存车取车任务)

	Common_data::Dispatch_process_type			m_dispatch_process_type ;			//调度流程类型
	park_table									m_park_table_msg;					//停车表单
	pick_table									m_pick_table_msg;					//取车表单
	Common_data::Car_type						m_car_type;							//车的大小

	Dispatch_command							m_dispatch_command;					//调度指令模块


	//地面雷达
	Rabbitmq_message							m_measure_statu_msg_1;
	Rabbitmq_message							m_measure_statu_msg_2;
	measure_info								m_measure_info_1;
	measure_info								m_measure_info_2;

	//出入口单片机
	Rabbitmq_message							m_in_mcpu_statu_msg_1;
	Rabbitmq_message							m_in_mcpu_statu_msg_2;
	in_mcpu_statu								m_in_mcpu_statu_1;
	in_mcpu_statu								m_in_mcpu_statu_2;
	Rabbitmq_message							m_out_mcpu_statu_msg_1;
	Rabbitmq_message							m_out_mcpu_statu_msg_2;
	out_mcpu_statu								m_out_mcpu_statu_1;
	out_mcpu_statu								m_out_mcpu_statu_2;


	std::chrono::system_clock::time_point		m_request_updata_time;	//请求更新时间
private:

};


#endif //NNXX_TESTS_DISPATCH_MANAGER_H
