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

#include "communication_can_base.h"

Communication_can_base::Communication_can_base()
{
	m_initialization_flag = false;
	m_communication_statu = COMMUNICATION_UNKNOW;

	mp_receive_data_thread = NULL;
	mp_analysis_data_thread = NULL;
	mp_send_data_thread = NULL;
	mp_encapsulate_data_thread = NULL;

	m_analysis_cycle_time = 1;//默认1000ms,就自动解析(接受list)
	m_encapsulate_cycle_time = 3;//默认1000ms,就自动发送一次状态信息
}

Communication_can_base::~Communication_can_base()
{
	communication_uninit();
}


//初始化 通信 模块。如下三选一
Error_manager Communication_can_base::communication_init()
{
	LOG(INFO) << " ---Communication_can_base::communication_init() run--- "<< this;

	return  communication_init_from_protobuf(COMMUNICATION_CAN_PARAMETER_PATH);
}

//初始化 通信 模块。从文件读取
Error_manager Communication_can_base::communication_init_from_protobuf(std::string prototxt_path)
{
	Communication_can_proto::Communication_can_parameter_all t_communication_can_parameter_all;
	if(!  proto_tool::read_proto_param(prototxt_path,t_communication_can_parameter_all) )
	{
		return Error_manager(CAN_READ_PROTOBUF_ERROR,MINOR_ERROR,
							 "Communication_can_base read_proto_param  failed");
	}

	return communication_init_from_protobuf(t_communication_can_parameter_all);
}

//初始化 通信 模块。从protobuf读取
Error_manager Communication_can_base::communication_init_from_protobuf(Communication_can_proto::Communication_can_parameter_all& communication_can_parameter_all)
{
	LOG(INFO) << " ---Communication_can_base::communication_init_from_protobuf() run--- "<< this;
	Error_manager t_error;

	int can_device_count = communication_can_parameter_all.communication_can_parameters_size();

	//检查can的数量
	if ( can_device_count <= 0 )
	{
		return Error_manager(Error_code::CAN_INIT_ERROR, Error_level::MINOR_ERROR,
							" Communication_can_base::communication_init_from_protobuf error, can_device_count <= 0 ");
	}
	else
	{
		for (int i = 0; i < can_device_count; ++i)
		{


			//按照prototxt的参数,创建can设备
			Can_device t_can_device;
			t_can_device.can_device_id = communication_can_parameter_all.communication_can_parameters(i).can_device_id();
			t_can_device.can_handle_id = -1;
			t_can_device.can_serial_number = communication_can_parameter_all.communication_can_parameters(i).can_serial_number();
			t_can_device.can_device_type = communication_can_parameter_all.communication_can_parameters(i).can_device_type();
			t_can_device.can_baud_rate = communication_can_parameter_all.communication_can_parameters(i).can_baud_rate();
			if ( t_can_device.can_device_type != VCI_USBCAN2 )
			{
			    return Error_manager(Error_code::CAN_INIT_ERROR, Error_level::MINOR_ERROR,
			    					" Communication_can_base::communication_init_from_protobuf error,  can_device_type != VCI_USBCAN2");
			}
			//can通道口设置, 如果can_port_id等于CAN_PORT_NUMBER, 则开启所有通道, 否则开启指定的单通道
			int t_can_port_id = communication_can_parameter_all.communication_can_parameters(i).can_port_id();
			if ( t_can_port_id == CAN_PORT_NUMBER )
			{
				for (int j = 0; j < CAN_PORT_NUMBER; ++j)
				{
					t_can_device.can_port_flag[j] = true;
				}
			}
			else
			{
				for (int j = 0; j < CAN_PORT_NUMBER; ++j)
				{
					if ( j == t_can_port_id )
					{
						t_can_device.can_port_flag[j] = true;
					}
					else
					{
						t_can_device.can_port_flag[j] = false;
					}
				}
			}

			//查重
			if ( m_can_device_map.find(t_can_device.can_device_id) == m_can_device_map.end() )
			{
				//can设备添加进map
				m_can_device_map[t_can_device.can_device_id] = t_can_device;
			}
			else
			{
				//把后者忽略掉, 提示一级故障
				LOG(INFO) << " Communication_can_base::communication_init_from_protobuf can_device_id repeat "<< this;
				t_error.error_manager_reset(Error_code::CAN_INDEX_REPEAT, Error_level::NEGLIGIBLE_ERROR,
			    					" Communication_can_base::communication_init_from_protobuf can_device_id repeat ");
			}
		}
	}

	//查找所有连接的USB_CAN卡设备信息
	VCI_BOARD_INFO p_board_information [50];
	int t_board_num=VCI_FindUsbDevice2(p_board_information);
	//双循环比较条形码, 找到对应的控制句柄
	for (auto iter = m_can_device_map.begin(); iter != m_can_device_map.end(); ++iter) 
	{
		int i = 0;
		for ( ; i < t_board_num; ++i)
		{
			if ( iter->second.can_serial_number == p_board_information[i].str_Serial_Num )
			{
				iter->second.can_handle_id = i;
				break;	//找到了, 就提前结束内部的循环,
			}
		}
		//判断是否找到, 就是检查前面的break是否执行
		if ( i == t_board_num )
		{
			char buf[256] = {0};
			sprintf(buf, " can_device can not find,  can_serial_number =  %s\n", iter->second.can_serial_number.c_str());
		    LOG(INFO) << " can_device can not find,  can_serial_number =  "<< iter->second.can_serial_number << this;
		    return Error_manager(Error_code::CAN_INIT_ERROR, Error_level::MINOR_ERROR,
								 buf);
		}
	}

	//启动can卡
	t_error = can_run();
	if ( t_error != Error_code::SUCCESS )
	{
		return t_error;
	}
	//启动通信, run thread
	t_error = communication_run();
	if ( t_error != Error_code::SUCCESS )
	{
		return t_error;
	}

	return Error_code::SUCCESS;
}



//启动can卡,
Error_manager Communication_can_base::can_run()
{
	for (auto iter = m_can_device_map.begin(); iter != m_can_device_map.end(); ++iter)
	{
		//此函数用以打开设备。注意一个设备只能打开一次。
		if(VCI_OpenDevice(iter->second.can_device_type, iter->second.can_handle_id,0) != 1 )
		{
			return Error_manager(Error_code::CAN_RUN_ERROR, Error_level::MINOR_ERROR,
								 " VCI_OpenDevice error ");
		}
		m_initialization_flag = true;

		//初始化参数，严格参数二次开发函数库说明书。
		VCI_INIT_CONFIG config;
		config.AccCode=0;
		config.AccMask=0xFFFFFFFF;
		config.Filter=1;//接收所有帧
		switch ( iter->second.can_baud_rate )
		{
		    case 10:
		    {
				config.Timing0=0x31;
				config.Timing1=0x1C;
		        break;
		    }
			case 20:
			{
				config.Timing0=0x18;
				config.Timing1=0x1C;
				break;
			}
			case 40:
			{
				config.Timing0=0x87;
				config.Timing1=0xFF;
				break;
			}
			case 50:
			{
				config.Timing0=0x09;
				config.Timing1=0x1C;
				break;
			}
			case 80:
			{
				config.Timing0=0x83;
				config.Timing1=0xFF;
				break;
			}
			case 100:
			{
				config.Timing0=0x04;
				config.Timing1=0x1C;
				break;
			}
			case 125:
			{
				config.Timing0=0x03;
				config.Timing1=0x1C;
				break;
			}
			case 200:
			{
				config.Timing0=0x81;
				config.Timing1=0xFA;
				break;
			}
			case 250:
			{
				config.Timing0=0x01;
				config.Timing1=0x1C;
				break;
			}
			case 400:
			{
				config.Timing0=0x80;
				config.Timing1=0xFA;
				break;
			}
			case 500:
			{
				config.Timing0=0x00;
				config.Timing1=0x1C;
				break;
			}
			case 666:
			{
				config.Timing0=0x80;
				config.Timing1=0xB6;
				break;
			}
			case 800:
			{
				config.Timing0=0x00;
				config.Timing1=0x16;
				break;
			}
			case 1000:
			{
				config.Timing0=0x00;
				config.Timing1=0x14;
				break;
			}
		    default:
		    {
				return Error_manager(Error_code::CAN_RUN_ERROR, Error_level::MINOR_ERROR,
									 " can_baud_rate error ");
		        break;
		    }
		}
		config.Mode=0;//正常模式


		for (int i = 0; i < CAN_PORT_NUMBER; ++i)
		{
			if ( iter->second.can_port_flag[i] )
			{
				//此函数用以初始化指定的CAN通道。有多个CAN通道时,需要多次调用。
				if(VCI_InitCAN(iter->second.can_device_type,iter->second.can_handle_id,i,&config) != 1)
				{
					VCI_CloseDevice(iter->second.can_device_type,iter->second.can_handle_id);
					return Error_manager(Error_code::CAN_RUN_ERROR, Error_level::MINOR_ERROR,
										 " VCI_InitCAN error ");
				}
				//此函数用以启动CAN卡的某一个CAN通道。有多个CAN通道时,需要多次调用。
				if(VCI_StartCAN(iter->second.can_device_type,iter->second.can_handle_id,i) != 1)
				{
					VCI_CloseDevice(iter->second.can_device_type,iter->second.can_handle_id);
					return Error_manager(Error_code::CAN_RUN_ERROR, Error_level::MINOR_ERROR,
										 " VCI_StartCAN error ");
				}
			}
		}
	}
	return Error_code::SUCCESS;
}

//启动通信, run thread
Error_manager Communication_can_base::communication_run()
{
	m_communication_statu = COMMUNICATION_READY;
	//启动4个线程。
	//接受线程默认循环, 内部的nn_recv进行等待,
	m_receive_condition.reset(false, false, false);
	mp_receive_data_thread = new std::thread(&Communication_can_base::receive_data_thread, this);
	//解析线程默认循环, 内部的wait_and_pop进行等待,
	m_analysis_data_condition.reset(false, true, false);
	mp_analysis_data_thread = new std::thread(&Communication_can_base::analysis_data_thread, this);
	//发送线程默认循环, 内部的wait_and_pop进行等待,
	m_send_data_condition.reset(false, true, false);
	mp_send_data_thread = new std::thread(&Communication_can_base::send_data_thread, this);
	//封装线程默认等待, ...., 超时 ms, 超时后主动 封装心跳和状态信息,
	m_encapsulate_data_condition.reset(false, false, false);
	mp_encapsulate_data_thread = new std::thread(&Communication_can_base::encapsulate_data_thread, this);

	return Error_code::SUCCESS;
}


//反初始化 通信 模块。
Error_manager Communication_can_base::communication_uninit()
{
	//终止list，防止 wait_and_pop 阻塞线程。
	m_receive_data_list.termination_list();
	m_send_data_list.termination_list();

	//杀死4个线程，强制退出
	if (mp_receive_data_thread)
	{
		m_receive_condition.kill_all();
	}
	if (mp_analysis_data_thread)
	{
		m_analysis_data_condition.kill_all();
	}
	if (mp_send_data_thread)
	{
		m_send_data_condition.kill_all();
	}
	if (mp_encapsulate_data_thread)
	{
		m_encapsulate_data_condition.kill_all();
	}
	//回收4个线程的资源
	if (mp_receive_data_thread)
	{
		mp_receive_data_thread->join();
		delete mp_receive_data_thread;
		mp_receive_data_thread = NULL;
	}
	if (mp_analysis_data_thread)
	{
		mp_analysis_data_thread->join();
		delete mp_analysis_data_thread;
		mp_analysis_data_thread = 0;
	}
	if (mp_send_data_thread)
	{
		mp_send_data_thread->join();
		delete mp_send_data_thread;
		mp_send_data_thread = NULL;
	}
	if (mp_encapsulate_data_thread)
	{
		mp_encapsulate_data_thread->join();
		delete mp_encapsulate_data_thread;
		mp_encapsulate_data_thread = NULL;
	}

	//清空list
	m_receive_data_list.clear_and_delete();
	m_send_data_list.clear_and_delete();

	m_communication_statu = COMMUNICATION_UNKNOW;

	if ( m_initialization_flag )
	{
		for (auto iter = m_can_device_map.begin(); iter != m_can_device_map.end(); ++iter)
		{
			VCI_CloseDevice(iter->second.can_device_type,iter->second.can_handle_id);//关闭设备。
		}
		m_initialization_flag = false;
	}


	return Error_code::SUCCESS;
}

//封装消息, 需要子类重载
Error_manager Communication_can_base::encapsulate_msg(Can_message* p_msg)
{
	Can_message* tp_msg = new Can_message(*p_msg);
	bool is_push = m_send_data_list.push(tp_msg);
	if ( is_push == false )
	{
		delete(tp_msg);
		tp_msg = NULL;
		return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
							 " Communication_can_base::encapsulate_msg error ");
	}
	return Error_code::SUCCESS;
}


void Communication_can_base::set_analysis_cycle_time(unsigned int analysis_cycle_time)
{
	m_analysis_cycle_time = analysis_cycle_time;
}
void Communication_can_base::set_encapsulate_cycle_time(unsigned int encapsulate_cycle_time)
{
	m_encapsulate_cycle_time = encapsulate_cycle_time;
}






//mp_receive_data_thread 接受线程执行函数，
//receive_data_thread 内部线程负责接受消息
void Communication_can_base::receive_data_thread()
{
	LOG(INFO) << " Communication_can_base::receive_data_thread start "<< this;

	//接收缓存, 重复利用, 为了防止频繁的分配和释放
	VCI_CAN_OBJ tp_receive_buf[3000];//接收缓存，设为3000为佳。
	int t_receive_size=0;			//实际接受帧数

	//通信接受线程, 负责接受socket消息, 并存入 m_receive_data_list
	while (m_receive_condition.is_alive())
	{
		m_receive_condition.wait_for_ex(std::chrono::microseconds(100));
		if ( m_receive_condition.is_alive() )
		{
			std::this_thread::yield();
			//遍历所有设备, 接受can消息
			for (auto iter = m_can_device_map.begin(); iter != m_can_device_map.end(); ++iter)
			{
				//遍历所有通道口, 接受can消息
				for (int i = 0; i < CAN_PORT_NUMBER; ++i)
				{
					if ( iter->second.can_port_flag[i] )
					{
						{//这个大括号表示只对 recv 和 send 加锁, 不要因为后面的复杂逻辑影响通信效率
							std::unique_lock<std::mutex> lk(m_mutex);
							t_receive_size = VCI_Receive(iter->second.can_device_type, iter->second.can_handle_id, i, tp_receive_buf, 3000, 0);
						}
						for (int j = 0; j < t_receive_size; ++j)
						{
							Can_message * tp_can_message = new Can_message;
							tp_can_message->can_device_id = iter->second.can_device_id;
							tp_can_message->can_port_id = i;
							tp_can_message->can_object = tp_receive_buf[j];
							if ( check_msg(tp_can_message) == SUCCESS )
							{
								bool is_push = m_receive_data_list.push(tp_can_message);

								//push成功之后, tp_can_message 内存的管理权限交给链表, 如果失败就要回收内存
								if ( is_push )
								{
									//唤醒解析线程一次,
									//m_analysis_data_condition.notify_all(false, true);
									//注:解析线程是常开的, 使用list里面的wait_and_pop来阻塞等待.
									//push里面会让 wait_and_pop 通过的
								}
								else
								{
									//push 失败, 就要回收内存
									delete(tp_can_message);
									tp_can_message = NULL;
									LOG(INFO) << " m_receive_data_list.push(tp_can_message) error "<< this;
								}
							}
							else
							{
								//check_msg 失败, 就要回收内存
								delete(tp_can_message);
								tp_can_message = NULL;
							}
						}
					}
				}
			}
		}
	}

	LOG(INFO) << " Communication_can_base::receive_data_thread end "<< this;
	return;
}

//检查消息是否有效, 判断这条消息是不是给我的.
Error_manager Communication_can_base::check_msg(Can_message*  p_msg)
{
	return Error_code::SUCCESS;

	//通过 p_msg 判断这条消息是不是给我的.
	//子类重载时, 增加自己模块的判断逻辑, 以后再写.
//	if ( p_msg->can_device_id == 0
//	&& p_msg->can_port_id == 0
//	&& p_msg->can_object.ID == 0x123)
//	{
//		return Error_code::SUCCESS;
//	}
//	else
//	{
//		//无效的消息,
//		return Error_code::INVALID_MESSAGE;
//	}
}


//mp_analysis_data_thread 解析线程执行函数，
//analysis_data_thread 内部线程负责解析消息
void Communication_can_base::analysis_data_thread()
{
	LOG(INFO) << " Communication_can_base::analysis_data_thread start "<< this;

	Error_manager t_error;
	//通信解析线程, 负责巡检m_receive_data_list, 并解析和处理消息
	while (m_analysis_data_condition.is_alive())
	{
		m_analysis_data_condition.wait();
		if ( m_analysis_data_condition.is_alive() )
		{
			std::this_thread::yield();
			//如果解析线程被主动唤醒, 那么就表示 收到新的消息, 那就遍历整个链表
			Can_message* tp_msg = NULL;
			//这里 wait_and_pop 会使用链表内部的 m_data_cond 条件变量来控制等待,
			//接受线程使用push的时候, 会唤解析醒线程并通过等待, 此时 m_analysis_data_condition 是一直通过的.
			//如果需要退出, 那么就要 m_receive_data_list.termination_list();	和 m_analysis_data_condition.kill_all();
			bool is_pop = m_receive_data_list.wait_and_pop(tp_msg);
			if ( is_pop )
			{
				if ( tp_msg != NULL )
				{
					//检查消息是否可以被处理
					t_error = check_executer(tp_msg);
					if ( t_error == SUCCESS)
					{
						//处理消息
						t_error = execute_msg(tp_msg);
						//执行结果不管, 由执行者进行特殊处理, 通信层不管执行者的错误返回
					}
					//check_executer 失败, 也不做处理,

					//处理完, 需要回收内存
					delete(tp_msg);
					tp_msg = NULL;
				}
			}
			//没有取出, 那么应该就是 m_termination_flag 结束了
		}
	}

	LOG(INFO) << " Communication_can_base::analysis_data_thread end "<< this;
	return;
}


//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
Error_manager Communication_can_base::check_executer(Can_message*  p_msg)
{
	//检查对应模块的状态, 判断是否可以处理这条消息

	return Error_code::SUCCESS;	
}

//处理消息
Error_manager Communication_can_base::execute_msg(Can_message*  p_msg)
{
	//先将 p_msg 转化为 对应的格式, 使用对应模块的protobuf来二次解析
	// 不能一直使用 Can_message*  p_msg, 这个是要销毁的
	//然后处理这个消息, 就是调用对应模块的 execute 接口函数
	//执行结果不管, 如果需要答复, 那么对应模块 在自己内部 封装一条消息发送即可.
	//子类重载, 需要完全重写, 以后再写.

	//注注注注注意了, 本模块只是用来做通信,
	//在做处理消息的时候, 可能会调用执行者的接口函数,
	//这里不应该长时间阻塞或者处理复杂的逻辑,
	//请执行者另开线程来处理任务.

	std::cout << "---------execute_msg---------------" << std::endl;
	std::cout << "p_msg->can_device_id = " << p_msg->can_device_id << std::endl;
	std::cout << "p_msg->can_port_id = " << p_msg->can_port_id << std::endl;
	std::cout << "p_msg->ID = " << p_msg->can_object.ID << std::endl;
	std::cout << "p_msg->Data = "  ;
	for (int i = 0; i < p_msg->can_object.DataLen; ++i)
	{
		std::cout << " "<< p_msg->can_object.Data[i] ;
	}
	std::cout <<  std::endl;

	return Error_code::SUCCESS;
}



//mp_send_data_thread 发送线程执行函数，
//send_data_thread 内部线程负责发送消息
void Communication_can_base::send_data_thread()
{
	LOG(INFO) << " Communication_can_base::send_data_thread start "<< this;

	//通信发送线程, 负责巡检m_send_data_list, 并发送消息
	while (m_send_data_condition.is_alive())
	{
		m_send_data_condition.wait();
		if ( m_send_data_condition.is_alive() )
		{
			std::this_thread::yield();

			Can_message* tp_msg = NULL;
			//这里 wait_and_pop 会使用链表内部的 m_data_cond 条件变量来控制等待,
			//封装线程使用push的时候, 会唤醒线程并通过等待, 此时 m_send_data_condition 是一直通过的.
			//如果需要退出, 那么就要 m_send_data_list.termination_list();	和 m_send_data_condition.kill_all();
			bool is_pop = m_send_data_list.wait_and_pop(tp_msg);
			if ( is_pop )
			{
				if ( tp_msg != NULL )
				{
					if ( m_can_device_map.find(tp_msg->can_device_id) != m_can_device_map.end() )
					{
						if ( m_can_device_map[tp_msg->can_device_id].can_port_flag[tp_msg->can_port_id] )
						{
							//这个大括号表示只对 recv 和 send 加锁, 不要因为后面的复杂逻辑影响通信效率
							std::unique_lock<std::mutex> lk(m_mutex);

							VCI_Transmit(m_can_device_map[tp_msg->can_device_id].can_device_type,
										 m_can_device_map[tp_msg->can_device_id].can_handle_id,
										 tp_msg->can_port_id, &(tp_msg->can_object), 1);
						}
						
					}
					
					delete(tp_msg);
					tp_msg = NULL;
				}
			}
			//没有取出, 那么应该就是 m_termination_flag 结束了

		}
	}

	LOG(INFO) << " Communication_can_base::send_data_thread end "<< this;
	return;
}



//mp_encapsulate_data_thread 封装线程执行函数，
//encapsulate_data_thread 内部线程负责封装消息
void Communication_can_base::encapsulate_data_thread()
{
	LOG(INFO) << " Communication_can_base::encapsulate_data_thread start "<< this;

	//通信封装线程, 负责定时封装消息, 并存入 m_send_data_list
	while (m_encapsulate_data_condition.is_alive())
	{
		bool t_pass_flag = m_encapsulate_data_condition.wait_for_millisecond(m_encapsulate_cycle_time);

		if ( m_encapsulate_data_condition.is_alive() )
		{
			std::this_thread::yield();
			//如果封装线程被主动唤醒, 那么就表示 需要主动发送消息,
			if ( t_pass_flag )
			{
				//主动发送消息,
			}
				//如果封装线程超时通过, 那么就定时封装心跳和状态信息
			else
			{
				encapsulate_send_data();
			}
		}
	}

	LOG(INFO) << " Communication_can_base::encapsulate_data_thread end "<< this;
	return;
}


//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
Error_manager Communication_can_base::encapsulate_send_data()
{
	//定时发送
	
//	return SUCCESS;



	Can_message* tp_msg = new Can_message;
	tp_msg->can_device_id = 0;
	tp_msg->can_port_id = 1;
	tp_msg->can_object.ID = 0x123;
	tp_msg->can_object.SendType = 0;
	tp_msg->can_object.RemoteFlag = 0;
	tp_msg->can_object.ExternFlag = 0;
	tp_msg->can_object.DataLen = 8;
	for(int i = 0; i < 8; i++)
	{
		tp_msg->can_object.Data[i] = i+63;
	}

	std::cout << "---------encapsulate_send_data---------------" << std::endl;
	std::cout << "p_msg->can_device_id = " << tp_msg->can_device_id << std::endl;
	std::cout << "p_msg->can_port_id = " << tp_msg->can_port_id << std::endl;
	std::cout << "p_msg->ID = " << tp_msg->can_object.ID << std::endl;
	std::cout << "p_msg->Data = "  ;
	for (int i = 0; i < tp_msg->can_object.DataLen; ++i)
	{
		std::cout << " "<< tp_msg->can_object.Data[i] ;
	}
	std::cout <<  std::endl;

	bool is_push = m_send_data_list.push(tp_msg);
	if ( is_push == false )
	{
		delete(tp_msg);
		tp_msg = NULL;
		return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
							 " Communication_can_base::encapsulate_msg error ");
	}
	return Error_code::SUCCESS;

}


