#include "workthread.h"
#include "alg_jd.h"
#include "common.h"
#include "balluffcamera.h"
#include "baslercamera.h"
#include "threadSend.h"
#include <PLCDevice.h>
#include "exportData.h"

extern AlgJd alg_jd[NumberOfSupportedCameras];	//检测胶点的AI算法

extern SysConf g_sys_conf;						//系统配置参数
extern DisplayLabelConf g_display_label_conf[NumberOfSupportedCameras];

extern int rotationAngle[NumberOfSupportedCameras];  //图片旋转角度
extern bool isNeedRotate[NumberOfSupportedCameras];

extern SyncQueue<std::pair<std::string, cv::Mat> >* g_save_queue;	//图片保存队列
extern SyncQueue<std::pair<int, cv::Mat> >* g_image_queue[NumberOfSupportedCameras];	//int表示一个目标拍了几张
extern SyncQueue<_UDPSendInfo> *UDP_Info_queue;
extern SyncQueue<_ExportDataInfo>* export_Data_Info_queue;
extern PLCDevice* m_PLCDevice;
extern bool g_debug_mode;

WorkThread::~WorkThread()
{
	stop();
	local_g_image_queue->put(std::make_pair(0, cv::Mat()));
	quit();
	wait();
}

void WorkThread::init(SyncQueue<std::pair<int, cv::Mat>>* image_ptr, ASyncQueue<bool>* result_ptr, int classid, int Num)
{
	local_camera_number = Num;
	local_classid = classid;
	local_g_image_queue = image_ptr;
	local_g_result_queue = result_ptr;
	b_quit = false;
	frame_total = 0;
}
void WorkThread::start_work()
{
	start(HighestPriority);
}
void WorkThread::stop()
{
	b_quit = true;
}

void WorkThread::run()
{
	try{
	uint32_t result_index = 0;
	while (!b_quit) {
		{//不要删掉这个括号，用来定义锁的作用域
			std::lock_guard<std::mutex> locker(g_sys_conf.lock);
			local_SysConf.save = g_sys_conf.save;
			local_SysConf.shoot[local_camera_number] = g_sys_conf.shoot[local_camera_number];
			local_SysConf.MisMatchAct = g_sys_conf.MisMatchAct;
			local_SysConf.ConfThreshold = g_sys_conf.ConfThreshold;//
			for (int i = 0; i < 3; i++)local_SysConf.no[local_camera_number][i] = g_sys_conf.no[local_camera_number][i];

#ifdef DRAW_RECT
			std::lock_guard<std::mutex> locker2(g_display_label_conf[local_camera_number].lock);
			local_DisplayLabelConf.leftButtonDownFlag = g_display_label_conf[local_camera_number].leftButtonDownFlag;
			local_DisplayLabelConf.Flag[0] = g_display_label_conf[local_camera_number].Flag[0];
			local_DisplayLabelConf.Flag[1] = g_display_label_conf[local_camera_number].Flag[1];
			local_DisplayLabelConf.originalPoint = g_display_label_conf[local_camera_number].originalPoint;
			local_DisplayLabelConf.processPoint = g_display_label_conf[local_camera_number].processPoint;
			local_DisplayLabelConf.RectVet[0] = g_display_label_conf[local_camera_number].RectVet[0];
			local_DisplayLabelConf.RectVet[1] = g_display_label_conf[local_camera_number].RectVet[1];
#endif
		}


		QDateTime now_ts = QDateTime::currentDateTime();
		std::pair<int, cv::Mat> element;
		local_g_image_queue->take(element);
		int unit_count = element.first;
		cv::Mat image = element.second;

		_UDPSendInfo UDPSendInfo;
		UDPSendInfo.FrameID = info_frame;
		UDPSendInfo.index = local_camera_number;

		_ExportDataInfo exportDataInfo;

		exportDataInfo.cameraId = local_camera_number;

		if (!image.data)
		{
			continue;	//图像为空，跳过
		}
		if (image.channels() == 1)
		{
			cv::cvtColor(image, image, CV_BGR2RGB);	//灰度图像转为彩色图像
		}
		if (local_SysConf.shoot[local_camera_number] == unit_count)
		{
			exportDataInfo.shotCounts = unit_count;
			std::vector<cv::Mat> vec_in;
			int w = image.cols;
			int h = image.rows / unit_count;
			for(int index=0;index<unit_count;index++)
			{
				cv::Rect temp_Rect(0, h * index, w, h);
				cv::Mat temp_image = image(temp_Rect).clone();
				if (isNeedRotate[local_camera_number]) {
					if(rotationAngle[local_camera_number] != (cv::ROTATE_90_COUNTERCLOCKWISE + 1))
					{
						cv::rotate(temp_image, temp_image, rotationAngle[local_camera_number]);
					}
				}
				vec_in.push_back(temp_image.clone());
			}

			std::vector<cv::Mat> vec_out;
			std::vector<std::vector<std::pair<int, cv::Rect> > > vec_results;
			QDateTime ts_start = QDateTime::currentDateTime();
			if(unit_count == 1){
				std::vector<std::pair<int, cv::Rect> > results;
				cv::Mat imagein,imageout;
				imagein = vec_in[0];
				alg_jd[local_camera_number].detect(imagein, imageout, results);
				vec_out.push_back(imageout.clone());
				vec_results.push_back(results);
			}else{
				alg_jd[local_camera_number].detect_batch(vec_in, vec_out, vec_results);
			}
			QDateTime ts_jd = QDateTime::currentDateTime();
			int time_process = ts_start.msecsTo(ts_jd);
			emit display_timecost(local_camera_number, time_process);
			UDPSendInfo.timecost = QString::number(time_process);
			exportDataInfo.timeCost = QString::number(time_process).toStdString();
			
			cv::Mat image1;
			cv::Mat image2;

			QString jd_no;
			for(int index=0;index<unit_count;index++)
			{
				jd_no += QString::number(vec_results[index].size())+",";
				exportDataInfo.jd[index] = vec_results[index].size();
				exportDataInfo.isJdExist[index] = vec_results[index].size() > 0;
			}
			jd_no.chop(1);
			emit display_jd_no(local_camera_number, jd_no);
			UDPSendInfo.JD = jd_no;

			bool IsNG = false;
			for(int index=0;index<unit_count;index++)
			{
				if(vec_results[index].size() < local_SysConf.no[local_camera_number][index])IsNG |= true;
				//if (vec_results[index].size() != 1)IsNG |= true;//反向训练
				if (local_SysConf.ConfThreshold == 0)IsNG = false;
				if (local_SysConf.save == 2)//三张照片分别存储
				{
					cv::Mat m = vec_in[index].clone();
					QString file_name = "D:/image/" +
						now_ts.toString("yyyy-MM-dd") +
						"/" + QString::number(local_camera_number + 1) +
						"/ALL/" +
						now_ts.toString("yyyy-MM-dd_HH-mm-ss_zzz_") + QString::number(local_camera_number + 1) +
						"#" + "_" + QString::number(index + 1) + ".bmp";
					g_save_queue->put(std::make_pair(file_name.toStdString(), m));
				}
			}

			if (unit_count >= 2){
				image1 = vec_out[(result_index) % 2].clone();
#ifdef DRAW_RECT
				IsNG|=CheckSelectRects(image1,vec_results,(result_index) % 2,local_DisplayLabelConf,0);
#endif
			}else {
				image1 = vec_out[0].clone();
#ifdef DRAW_RECT
				IsNG|=CheckSelectRects(image1,vec_results,0,local_DisplayLabelConf,0);
#endif
			}
#ifdef DRAW_RECT
			DrawSelectRects(image1, local_DisplayLabelConf, 0);
#endif
			
			if (unit_count >= 3) { 
				image2 = vec_out[2].clone();
#ifdef DRAW_RECT
				DrawSelectRects(image2, local_DisplayLabelConf, 1);
				IsNG|=CheckSelectRects(image1,vec_results,2,local_DisplayLabelConf,1);
#endif
			}
			result_index++;
			exportDataInfo.isNg = IsNG;

			if (!IsNG)
			{
				if (!g_debug_mode) 
				{
					emit event_ok(local_camera_number);
					local_g_result_queue->put(true);
				}
			}
			else
			{
				if (!g_debug_mode)
				{
					emit event_ng(local_camera_number);
					local_g_result_queue->put(false);
				}
					
				if ((local_SysConf.save == 2) || (local_SysConf.save == 1))
				{
					for(int index=0;index<unit_count;index++)
					{
						cv::Mat m = vec_in[index].clone();
						QString file_name = "D:/image/" +
							now_ts.toString("yyyy-MM-dd") +
							"/" + QString::number(local_camera_number + 1) +
							"/ng/" + QString::number(index) + "/" +
							now_ts.toString("yyyy-MM-dd_HH-mm-ss_zzz_") + "_" + QString::number(index) + ".bmp";
						g_save_queue->put(std::make_pair(file_name.toStdString(), m));

						m = vec_out[index].clone();
						file_name = "D:/image/" +
							now_ts.toString("yyyy-MM-dd") +
							"/" + QString::number(local_camera_number + 1) +
							"/ng_result/" + QString::number(index) + "/" +
							now_ts.toString("yyyy-MM-dd_HH-mm-ss_zzz_") + "_" + QString::number(index) + ".bmp";
						g_save_queue->put(std::make_pair(file_name.toStdString(), m));
					}
				}
			}
			if (!g_debug_mode) 
			{
				emit display_check_total(local_camera_number, ++frame_total);
				exportDataInfo.cameraTotal = frame_total;

				emit notify(local_camera_number, 0, image1);
				if (unit_count >= 3)
					emit notify(local_camera_number, 1, image2);
			}
			
		}
		else 
		{	
			//保证不错位
			if (!g_debug_mode) 
			{
				if (local_SysConf.MisMatchAct == 1)//as ng
					emit event_ng(local_camera_number);
				else if (local_SysConf.MisMatchAct == 0)//as ok
					emit event_ok(local_camera_number);
				emit display_check_total(local_camera_number, ++frame_total);
				qDebug() << local_camera_number << "#camera# " << now_ts.toString("yyyy-MM-dd_HH-mm-ss_zzz_") << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  " << unit_count;
			}
		}
#ifdef __UDPSend
		UDP_Info_queue->put(UDPSendInfo);
#endif
#ifdef __ExportData
		export_Data_Info_queue->put(exportDataInfo);
#endif
	}
	}
	catch (cv::Exception& e)
	{
		const char* err_msg = e.what();
		std::cout << "exception caught: " << err_msg << std::endl; 
	}
}