#include "QtWidgetsApplication.h"

QtWidgetsApplication::QtWidgetsApplication(QWidget *parent)
    : QMainWindow(parent)
{

    ui.setupUi(this);
	// 获取 控制系统 单例并初始化
	Mycontrol::getInstance().init();

	//相机需要的显示控件
	m_scene = new QGraphicsScene(this);
	ui.imgView->setScene(m_scene);

	//保存路径
	ui.edtSaveDir->setText("D:/");
	//TCT检测显示需要
	tct_pixmapItem = new QGraphicsPixmapItem(tct_pixmap);
	tct_scene = new QGraphicsScene(this);
	tct_scene->addItem(tct_pixmapItem);

	//TCT模型处理的线程
	my_TCT = new TCT(this);
	m_infQthread = new QThread(nullptr);
	my_TCT->moveToThread(m_infQthread);

	//TCT模型处理需要的信号与槽
	connect(this, &QtWidgetsApplication::emit_img, my_TCT, &TCT::main_module);
	connect(my_TCT, &TCT::em_img, this, &QtWidgetsApplication::input_img);
	m_infQthread->start();
	
	//定时器定时获取当前位置
	QTimer* timer = new QTimer(this);
	timer->setInterval(50);  // 设置定时器间隔为 50 毫秒
	timer->setSingleShot(false);  // 非单次触发，持续运行
	connect(timer, &QTimer::timeout, [this]() {
		Mycontrol& Mycontrol = Mycontrol::getInstance();
		ui.m_xpos->setValue(Mycontrol::getInstance().getXPos());
		ui.m_ypos->setValue(Mycontrol::getInstance().getYPos());
		ui.m_zpos->setValue(Mycontrol::getInstance().getZPos());
		});
	timer->start();
}

QtWidgetsApplication::~QtWidgetsApplication()
{

}

//选择相机
void QtWidgetsApplication::on_pb_camera_clicked() {

	QString currentText = ui.CameraBox->currentText();       // 获取文本
	if (currentText == "haikang camera")
	{
		// 创建相机线程，和信号与槽
		cam_thread = new QThread(this);
		Hacm_worker = new haikang(this);
		Hacm_worker->moveToThread(cam_thread);
		connect(cam_thread, &QThread::started, Hacm_worker, &haikang::GrabThreadProcess);
		//connect(Hacm_worker, &haikang::img_redy, this, &QtWidgetsApplication::do_hai_img_redy); //弃用
		m_hwndDisplay = (HWND)ui.imgView->winId();//弃用
		connect(cam_thread, &QThread::finished, Hacm_worker, &haikang::finish); 
		connect(Hacm_worker, &haikang::img_to, this, &QtWidgetsApplication::hai_img_redy);
		cam_thread->start();
		setSlideSpinboxCheckboxSync();
	}
	if (currentText == "flir camera")
	{
		
		qRegisterMetaType<ImagePtr>("ImagePtr");
		// 创建相机线程，和信号与槽
		cam_thread = new QThread(this);
		cam_worker = new M_camera(nullptr);
		cam_worker->moveToThread(cam_thread);
		connect(cam_thread, &QThread::started, cam_worker, &M_camera::do_start);//线程开始，让相机初始化
		connect(cam_worker, &M_camera::img_redy, this, &QtWidgetsApplication::do_img_redy);
		cam_thread->start();
		//让曝光，增益的Slide和Spinbox同步
		setSlideSpinboxCheckboxSync();
	}

}

// 将海康相机传回来的图片进行显示
void QtWidgetsApplication::hai_img_redy(QImage image, void* handle)
{
	hikimage = image;    //往tct里面送的时候用
	HK_handle = handle; //相机句柄
	m_scene->clear();  // 清除旧图像
	QPixmap pixmap = QPixmap::fromImage(image);
	pixmapItem = m_scene->addPixmap(pixmap);

	ui.imgView->fitInView(pixmapItem, Qt::KeepAspectRatio);
	ui.imgView->setScene(m_scene);
	ui.imgView->show();
}

//将海康相机传回来的图片进行显示  //SB处理办法 
void QtWidgetsApplication::do_hai_img_redy(MV_FRAME_OUT stImageInfo, void *handle)
{
	//HK_handle = handle;
	//MV_DISPLAY_FRAME_INFO stDisplayInfo = {0};
	//stDisplayInfo.hWnd = m_hwndDisplay;   //显示的句柄 这种显示方式相当于绑定句柄
	//stDisplayInfo.pData = stImageInfo.pBufAddr;
	//stDisplayInfo.nDataLen = stImageInfo.stFrameInfo.nFrameLen;
	//stDisplayInfo.nWidth = stImageInfo.stFrameInfo.nWidth;
	//stDisplayInfo.nHeight = stImageInfo.stFrameInfo.nHeight;
	//stDisplayInfo.enPixelType = stImageInfo.stFrameInfo.enPixelType;
	//MV_CC_DisplayOneFrame(handle, &stDisplayInfo);
	//MV_CC_FreeImageBuffer(handle, &stImageInfo);
}


  
//将flir相机传回来的图片进行显示
void QtWidgetsApplication::do_img_redy(ImagePtr pResultImage)
{
	const size_t width = pResultImage->GetWidth();
	const size_t height = pResultImage->GetHeight();
	const unsigned char* pData = (const unsigned char*)pResultImage->GetData();
	// 根据像素格式创建 QImage
	QImage qImage(pData, static_cast<int>(width), static_cast<int>(height),
		static_cast<int>(width * pResultImage->GetBitsPerPixel() / 8),
		QImage::Format_RGB888);  // 根据实际情况调整格式
	
	m_scene->clear();  // 清除旧图像
	QPixmap pixmap = QPixmap::fromImage(qImage);
	pixmapItem = m_scene->addPixmap(pixmap);
	
	ui.imgView->fitInView(pixmapItem, Qt::KeepAspectRatio);
	ui.imgView->setScene(m_scene);
	ui.imgView->show();
}


int QtWidgetsApplication::resetExposure() {

	Spinnaker::GenApi::INodeMap& nodeMap = cam_worker->pCam->GetNodeMap();

	CEnumerationPtr exposureAuto = nodeMap.GetNode("ExposureAuto");
	exposureAuto->SetIntValue(exposureAuto->GetEntryByName("Continuous")->GetValue());
	 
	return 0;
} 


int QtWidgetsApplication::configureExposure(double exposure) {

	Spinnaker::GenApi::INodeMap& nodeMap = cam_worker->pCam->GetNodeMap();

	CEnumerationPtr exposureAuto = nodeMap.GetNode("ExposureAuto");
	exposureAuto->SetIntValue(exposureAuto->GetEntryByName("Off")->GetValue());

	CEnumerationPtr exposureMode = nodeMap.GetNode("ExposureMode");
	exposureMode->SetIntValue(exposureMode->GetEntryByName("Timed")->GetValue());

	CFloatPtr exposureTime = nodeMap.GetNode("ExposureTime");
	exposureTime->SetValue(exposure);

	return 0;
}


void QtWidgetsApplication::setSlideSpinboxCheckboxSync() {
	QString currentText = ui.CameraBox->currentText();
	if (currentText == "flir camera") {
		// Exposure
		connect(ui.sldExposure, &QSlider::valueChanged, ui.spinExposure, [this](int sliderValue) {
			ui.spinExposure->setValue(static_cast<double>(sliderValue));
			});
		connect(ui.spinExposure, QOverload<double>::of(&QDoubleSpinBox::valueChanged), ui.sldExposure, [this](double spinValue) {
			ui.sldExposure->setValue(static_cast<int>(spinValue));
			configureExposure(spinValue);
			});
		connect(ui.chkExposure, &QCheckBox::toggled, [this](bool checked) {
			bool isEnabled = !checked;
			ui.spinExposure->setEnabled(isEnabled);
			ui.sldExposure->setEnabled(isEnabled);
			resetExposure();
			});

		// Gain
		connect(ui.sldGain, &QSlider::valueChanged, ui.spinGain, [this](int sliderValue) {
			ui.spinGain->setValue(static_cast<double>(sliderValue) / 100.0);
			});
		connect(ui.spinGain, QOverload<double>::of(&QDoubleSpinBox::valueChanged), ui.sldGain, [this](double spinValue) {
			ui.sldGain->setValue(static_cast<int>(spinValue * 100));
			configureGain(spinValue);
			});
		connect(ui.chkGain, &QCheckBox::toggled, [this](bool checked) {
			bool isEnabled = !checked;
			ui.spinGain->setEnabled(isEnabled);
			ui.sldGain->setEnabled(isEnabled);
			resetGain();
			});
	}
	if (currentText =="haikang camera") {
		// Exposure
		connect(ui.sldExposure, &QSlider::valueChanged, ui.spinExposure, [this](int sliderValue) {
			ui.spinExposure->setValue(static_cast<double>(sliderValue));
			});
		connect(ui.spinExposure, QOverload<double>::of(&QDoubleSpinBox::valueChanged), ui.sldExposure, [this](double spinValue) {
			ui.sldExposure->setValue(static_cast<int>(spinValue));
			HK_configureExposure(spinValue);
			});
		connect(ui.chkExposure, &QCheckBox::toggled, [this](bool checked) {
			bool isEnabled = !checked;
			ui.spinExposure->setEnabled(isEnabled);
			ui.sldExposure->setEnabled(isEnabled);
			HK_resetExposure();
			});

		// Gain
		connect(ui.sldGain, &QSlider::valueChanged, ui.spinGain, [this](int sliderValue) {
			ui.spinGain->setValue(static_cast<double>(sliderValue) / 100.0);
			});
		connect(ui.spinGain, QOverload<double>::of(&QDoubleSpinBox::valueChanged), ui.sldGain, [this](double spinValue) {
			ui.sldGain->setValue(static_cast<int>(spinValue * 100));
			HK_configureGain(spinValue);
			});
		connect(ui.chkGain, &QCheckBox::toggled, [this](bool checked) {
			bool isEnabled = !checked;
			ui.spinGain->setEnabled(isEnabled);
			ui.sldGain->setEnabled(isEnabled);
			HK_resetGain();
			});
	}
	
}

void QtWidgetsApplication::HK_resetGain() {


	MV_CC_SetExposureAutoMode(HK_handle, 2);

}

void QtWidgetsApplication::HK_resetExposure() 
{
	MV_CC_SetGain(HK_handle, 2);
}

void QtWidgetsApplication::HK_configureExposure(double exposure)
{
	MV_CC_SetFloatValue(HK_handle, "ExposureTime", exposure);
}

void QtWidgetsApplication::HK_configureGain(double gain)
{
	MV_CC_SetFloatValue(HK_handle, "Gain", gain);
}

int QtWidgetsApplication::configureGain(double gain) {
	Spinnaker::GenApi::INodeMap& nodeMap = cam_worker->pCam->GetNodeMap();

	CEnumerationPtr gainAuto = nodeMap.GetNode("GainAuto");
	gainAuto->SetIntValue(gainAuto->GetEntryByName("Off")->GetValue());

	CFloatPtr gainValue = nodeMap.GetNode("Gain");
	gainValue->SetValue(gain);

	return 0;
}

int QtWidgetsApplication::resetGain() {
	Spinnaker::GenApi::INodeMap& nodeMap = cam_worker->pCam->GetNodeMap();

	CEnumerationPtr gainAuto = nodeMap.GetNode("GainAuto");
	gainAuto->SetIntValue(gainAuto->GetEntryByName("Continuous")->GetValue());

	return 0;
}

//单张图片的保存
void QtWidgetsApplication::on_btnSingleImageSave_clicked() {

	QString currentText = ui.CameraBox->currentText();
	if (currentText == "flir camera") {
		qDebug() << "Single image save clicked";
		QString fileName = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
		QString absPath = ui.edtSaveDir->text() + "/" + fileName + ".tif";
		qDebug() << "Save path: " << absPath << "";

		ImagePtr pImage = cam_worker->pCam->GetNextImage(1000);
		if (pImage->IsIncomplete()) {
			qDebug() << "Image incomplete in 1s: " << Image::GetImageStatusDescription(pImage->GetImageStatus()) << "...";
		}
		ImagePtr pConvertedImage = processor.Convert(pImage, PixelFormat_RGB8);
		pConvertedImage->Save(absPath.toStdString().c_str());
	}
	if (currentText == "haikang camera") {
	
	
	
	
	}
	
}

//选择保存路径
void QtWidgetsApplication::on_btnSaveDir_clicked() {
	qDebug() << "Choose save dir clicked";
	QString dirPath = QFileDialog::getExistingDirectory(
		this, 
		QString::fromUtf8(u8"请选择图像保存路径")
	);
	qDebug() << "Choose save dir: " << dirPath << "";
	ui.edtSaveDir->setText(dirPath);
}


// 将TCT检测的图片进行显示
void QtWidgetsApplication::input_img(QImage image)
{
	in_image = image;
	// 显示经过网络检测后的图片
	this->ui.TCT_View->setScene(tct_scene);
	tct_pixmap = QPixmap::fromImage(in_image);
	tct_pixmapItem = tct_scene->addPixmap(tct_pixmap);
	// 自适应显示图片
	ui.TCT_View->fitInView(tct_pixmapItem, Qt::KeepAspectRatio);
	ui.TCT_View->setRenderHint(QPainter::Antialiasing);  // 抗锯齿
	ui.TCT_View->setDragMode(QGraphicsView::ScrollHandDrag);  // 启动手动拖动模式
	ui.TCT_View->show();
}

// 将ImagePtr转换成QImage
QImage convertToQImage(const ImagePtr& pImage)
{
	// 获取图像尺寸
	int width = pImage->GetWidth();  
	int height = pImage->GetHeight();

	// 获取像素数据指针（假设为 uchar* 类型）
	const uchar* pData = reinterpret_cast<const uchar*>(pImage->GetData());

	// 获取每行的字节数（步长）
	int stride = width * 3; // 假设存在此方法，若不存在可设为 width * 3

	// 构造 QImage
	QImage qImage(pData, width, height, stride, QImage::Format_RGB888);

	// 返回深拷贝，避免原始图像数据被释放导致 QImage 无效
	return qImage.copy();
}

// 将相机图片输入到网络的线程中 
void QtWidgetsApplication::on_pb_model_clicked()
{
	/*QString fileName = QFileDialog::getOpenFileName(this, "选择图片", "D:/TCT_down/dataset/test/images", "Images (*.png *.jpg)");
	QImage image(fileName);*/ 
	QString currentText = ui.CameraBox->currentText();
	if (currentText == "flir camera") {
		ImagePtr pImage = cam_worker->pCam->GetNextImage(1000);
		if (pImage->IsIncomplete()) {
			qDebug() << "Image incomplete in 1s: " << Image::GetImageStatusDescription(pImage->GetImageStatus()) << "...";
		}
		ImagePtr pConvertedImage = processor.Convert(pImage, PixelFormat_RGB8);
		QImage image = convertToQImage(pConvertedImage);
		emit emit_img(image);
	}
	if (currentText == "haikang camera") {
		
		emit emit_img(hikimage);
	}
	
}

// 运动控制
void QtWidgetsApplication::on_btnUp_clicked() {
	double zdis = ui.spinZDis->value();
	qDebug() << "up clicked, move up: " << zdis << "um";
	Mycontrol::getInstance().moveBy(3, zdis * -1e-3);
}

void QtWidgetsApplication::on_btnDown_clicked() {
	double zdis = ui.spinZDis->value();
	qDebug() << "up clicked, move up: " << zdis << "um";
	Mycontrol::getInstance().moveBy(3, -zdis * -1e-3);
}

void QtWidgetsApplication::on_btnLeft_clicked() {
	double xdis = ui.spinXDis->value();
	qDebug() << "up clicked, move up: " << xdis << "um";
	Mycontrol::getInstance().moveBy(2, -xdis * -1e-3);
}

void QtWidgetsApplication::on_btnRight_clicked() {
	double xdis = ui.spinXDis->value();
	qDebug() << "up clicked, move up: " << xdis << "um";
	Mycontrol::getInstance().moveBy(2, xdis * -1e-3);
}

void QtWidgetsApplication::on_btnForward_clicked() {
	double ydis = ui.spinYDis->value();
	qDebug() << "up clicked, move up: " << ydis << "um";
	Mycontrol::getInstance().moveBy(1, -ydis * -1e-3);
}

void QtWidgetsApplication::on_btnBackward_clicked() {
	double ydis = ui.spinYDis->value();
	qDebug() << "up clicked, move up: " << ydis << "um";
	Mycontrol::getInstance().moveBy(1, ydis * -1e-3);
}


double sharpnessSobel(cv::Mat image) {
	cv::Mat roi = image(cv::Rect(968, 768, 512, 512));
	cv::Mat gray;
	cv::cvtColor(roi, gray, cv::COLOR_BGR2GRAY);
	cv::GaussianBlur(gray, gray, cv::Size(5, 5), 0);
	cv::Mat sobelx, sobely;
	cv::Sobel(gray, sobelx, CV_64F, 1, 0, 3);
	cv::Sobel(gray, sobely, CV_64F, 0, 1, 3);
	cv::Mat magnitude;
	cv::magnitude(sobelx, sobely, magnitude);
	return cv::mean(magnitude)[0];
}