#include "CaptureThreadBasler.h"
#include <QtWidgets/QApplication>
#include "PLCDevice.h"
#include "common.h"
#include <qdebug.h>
extern PLCDevice * m_PLCDevice;
//-----------------------------------------------------------------------------
CaptureThreadBasler::CaptureThreadBasler(Pylon::CBaslerUniversalInstantCamera* pCurrDev, bool boTerminated,int Num,int shoot) :
	pDev_( pCurrDev ), boTerminated_( boTerminated ),Local_Num(Num)
//-----------------------------------------------------------------------------
{
	p_unit_queue = new ASyncQueue<cv::Mat>(Unit_Queue_Size);
	Shoot_Num = shoot;
}
CaptureThreadBasler::~CaptureThreadBasler()
{
	delete p_unit_queue;
}
//-----------------------------------------------------------------------------
void CaptureThreadBasler::process(void)
//-----------------------------------------------------------------------------
{
	bool last_high = false;
	bool last_result = false;
	try
	{
		CSampleConfigurationEventHandler *CfgEvent=NULL;
		CfgEvent = new CSampleConfigurationEventHandler;
		CfgEvent->channel_ = Local_Num;
		pDev_->RegisterConfiguration(CfgEvent, Pylon::RegistrationMode_Append, Pylon::Cleanup_None);

		CSampleImageEventHandler ImageEvent;
		ImageEvent.p_image_queue_ = p_image_queue;
		ImageEvent.p_unit_queue_ = p_unit_queue;
		ImageEvent.p_shooted_queue_ = p_shooted_queue;
		ImageEvent.p_debug_queue_ = p_debug_queue;
		ImageEvent.m_cntGrabbedImages_ = &m_cntGrabbedImages;
		ImageEvent.Shoot_Num_ = Shoot_Num;
		ImageEvent.pDev__ = pDev_;
		pDev_->RegisterImageEventHandler(&ImageEvent, Pylon::RegistrationMode_Append, Pylon::Cleanup_None);

		CSampleCameraEventHandler BurstEvent;
		BurstEvent.p_unit_queue_ = p_unit_queue;
		BurstEvent.p_result_wait_queue_ = p_result_wait_queue;
		BurstEvent.p_result_queue_ = p_result_queue;
		BurstEvent.p_shooted_queue_ = p_shooted_queue;
		BurstEvent.p_double_queue_ = p_double_queue;
		BurstEvent.p_image_queue_ = p_image_queue;
		BurstEvent.pDev__ = pDev_;
		BurstEvent.pCaptureThreadBasler = this;

		m_threadFunc.pDev__ = pDev_;
		m_threadFunc.p_result_queue_ = p_result_queue;
		m_threadFunc.p_double_queue_ = p_double_queue;
		m_threadFunc.m_IOTimer_ = m_IOTimer;
#ifndef USB_BASLER_NEW_FW
		if (pDev_->TriggerSelector.TrySetValue(Basler_UniversalCameraParams::TriggerSelector_FrameBurstStart))
		{
			pDev_->TriggerMode.SetValue(Basler_UniversalCameraParams::TriggerMode_On);
			pDev_->TriggerSource.SetValue(Basler_UniversalCameraParams::TriggerSource_Line1);
			pDev_->TriggerActivation.SetValue(Basler_UniversalCameraParams::TriggerActivation_RisingEdge);
			pDev_->AcquisitionBurstFrameCount.SetValue(Shoot_Num);
			if (pDev_->EventSelector.TrySetValue(Basler_UniversalCameraParams::EventSelector_FrameBurstStart))
			{
				if (!pDev_->EventNotification.TrySetValue(Basler_UniversalCameraParams::EventNotification_On))
				{
					pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_GenICamEvent);
				}

				m_IOTimer = new QTimer();
				connect(m_IOTimer, SIGNAL(timeout()), this, SLOT(ioTimeout()));
				m_IOTimer->setSingleShot(true);
				BurstEvent.ioTimer = m_IOTimer;
				pDev_->RegisterCameraEventHandler(&BurstEvent, "EventFrameBurstStartData", eMyFrameBurstStartEvent, Pylon::RegistrationMode_Append, Pylon::Cleanup_None);
			}

			if(pDev_->EventSelector.TrySetValue("Line1RisingEdge"))
			{
				pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_Off);
			}
			if(pDev_->EventSelector.TrySetValue("Line1FallingEdge"))
			{
				pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_Off);
			}
		}
#else
		/*Set here*/
		if (pDev_->TriggerSelector.TrySetValue(Basler_UniversalCameraParams::TriggerSelector_FrameBurstStart))
		{
			DEBUG("    TriggerSelector_FrameBurstStart\n");
			pDev_->TriggerMode.SetValue(Basler_UniversalCameraParams::TriggerMode_Off);
			if(pDev_->EventSelector.TrySetValue(Basler_UniversalCameraParams::EventSelector_FrameBurstStart))
			{
				DEBUG("    EventSelector_FrameBurstStart\n");
				pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_Off);
			}
		}

		pDev_->RegisterCameraEventHandler(&BurstEvent, "EventLine1RisingEdgeData", Line1RisingEdge, Pylon::RegistrationMode_Append, Pylon::Cleanup_None);
		pDev_->EventSelector.SetValue("Line1RisingEdge");
#ifdef IMM_PROCESS
		pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_Off);
#else
		pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_On);
#endif
		pDev_->RegisterCameraEventHandler(&BurstEvent, "EventLine1FallingEdgeData", Line1FallingEdge, Pylon::RegistrationMode_Append, Pylon::Cleanup_None);
		pDev_->EventSelector.SetValue("Line1FallingEdge");
#ifdef IMM_PROCESS
		pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_Off);
#else
		pDev_->EventNotification.SetValue(Basler_UniversalCameraParams::EventNotification_On);
#endif

#endif
		const unsigned int timeout_ms = 200;
		// This smart pointer will receive the grab result data.
		Pylon::CGrabResultPtr ptrGrabResult;

		pDev_->StartGrabbing();

		m_Timer = new QTimer();
		connect(m_Timer, SIGNAL(timeout()), this, SLOT(fpsTimeout()));
		m_Timer->start(1000);
		Ready = true;
		while (!boTerminated_)
		{
			// Retrieve grab results and notify the camera event and image event handlers.
			pDev_->RetrieveResult(timeout_ms, ptrGrabResult, Pylon::TimeoutHandling_Return);
#if defined (IMM_FEED_BACK) || defined (CAP_FEED_BACK)
			m_threadFunc.SendFeedBack(ImageCap);
#endif
			QCoreApplication::processEvents();//Make sure the timer is triggered
		}
#ifndef USB_BASLER_NEW_FW
		// Disable sending Event Overrun events.
		if (pDev_->EventSelector.TrySetValue(Basler_UniversalCameraParams::EventSelector_FrameBurstStart))
		{
			pDev_->EventNotification.TrySetValue(Basler_UniversalCameraParams::EventNotification_Off);
		}
		if (m_IOTimer) delete m_IOTimer;
#endif
		if (m_Timer) delete m_Timer;
		pDev_->StopGrabbing();
		pDev_->Close();
		pDev_->GrabCameraEvents = false;
		pDev_->DeregisterConfiguration(CfgEvent);
		pDev_->DeregisterImageEventHandler(&ImageEvent);
#ifndef USB_BASLER_NEW_FW
		pDev_->DeregisterCameraEventHandler(&BurstEvent, "EventFrameBurstStartData");
#endif
    }
    catch(const Pylon::GenericException& e)
    {
        emit error( QString::fromStdString( e.GetDescription()) );
		std::cout << e.GetSourceLine()<<e.GetDescription() << std::endl;
		pDev_->StopGrabbing();
    }
}

void CaptureThreadBasler::fpsTimeout()
{
	uint64_t delta = m_cntGrabbedImages - m_cntLastGrabbedImages;
	m_cntLastGrabbedImages = m_cntGrabbedImages;
	QString data = QString("%1").arg(delta);
	emit updateStatistics(data.left(4), Local_Num);
}

void CaptureThreadBasler::ioTimeout()
{
	pDev_->UserOutputSelector.SetValue(Basler_UniversalCameraParams::UserOutputSelector_UserOutput1);
	pDev_->UserOutputValue.SetValue(false);

	pDev_->UserOutputSelector.SetValue(Basler_UniversalCameraParams::UserOutputSelector_UserOutput3);
	pDev_->UserOutputValue.SetValue(false);

}