#include "CaptureThread.h"
#include "common.h"

extern bool g_debug_mode;	//相机调试模式，工作模式必须停止状态才能打开

//-----------------------------------------------------------------------------
CaptureThread::CaptureThread( Device* pCurrDev, bool boTerminated, FunctionInterface* pFI_ ,int Num) :
    pDev_( pCurrDev ), boTerminated_( boTerminated ), requestPendingForDisplay_( INVALID_ID ), pFI_( pFI_ ),Local_Num(Num)
//-----------------------------------------------------------------------------
{
	p_unit_queue = new ASyncQueue<cv::Mat>(Unit_Queue_Size);
}

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

CaptureThread::~CaptureThread()
{
	delete p_unit_queue;
}
//-----------------------------------------------------------------------------
void CaptureThread::process( void )
//-----------------------------------------------------------------------------
{
    try
    {
		//Line5回调
		mvIMPACT::acquire::GenICam::EventControl pEventCtrl_(pDev_);
		//pEventCtrl_.eventSelector.writeS("Line5FallingEdge");
		//pEventCtrl_.eventNotification.writeS("Off");
		//pEventCtrl_.eventSelector.writeS("Line5RisingEdge");
		//pEventCtrl_.eventNotification.writeS("Off");
		pEventCtrl_.eventSelector.writeS("Line5AnyEdge");
#ifdef IMM_PROCESS
		pEventCtrl_.eventNotification.writeS("Off");
#else
		pEventCtrl_.eventNotification.writeS("On");
#endif

#ifndef IMM_PROCESS
		EventCallback eventCallback(&pEventCtrl_);
		eventCallback.p_unit_queue_ = p_unit_queue;
		eventCallback.p_image_queue_ = p_image_queue;
		eventCallback.p_result_wait_queue_ = p_result_wait_queue;
		eventCallback.p_shooted_queue_ = p_shooted_queue;
		eventCallback.p_double_queue_ = p_double_queue;
		eventCallback.m_pMVCamera = pDev_;
		eventCallback.pCaptureThread = this;
		eventCallback.registerComponent(pEventCtrl_.eventLine5AnyEdge);
#endif

		m_threadFunc.m_pMVCamera = pDev_;
		m_threadFunc.p_result_queue_ = p_result_queue;
		m_threadFunc.p_double_queue_ = p_double_queue;

		//相机掉线回调
		CIwtCameraLostCallbackMV cam_lost_cb;
		cam_lost_cb.channel_ = Local_Num;
		if (cam_lost_cb.registerComponent(pDev_->state) != true)
		{
			std::cout << "ERROR: Unable to register the camera's lost CallBack function!\n";
		}
		//图像采集循环
        TDMR_ERROR result = DMR_NO_ERROR;
        while( ( result = static_cast< TDMR_ERROR >( pFI_->imageRequestSingle() ) ) == DMR_NO_ERROR ) {};
        if( result != DEV_NO_FREE_REQUEST_AVAILABLE )
        {
            qDebug() << "'FunctionInterface.imageRequestSingle' returned with an unexpected result: " << QString::fromStdString( mvIMPACT::acquire::ImpactAcquireException::getErrorCodeAsString( result ) );
        }
        manuallyStartAcquisitionIfNeeded( pDev_, *pFI_ );
        int cnt = 0;

        // run thread loop
        mvIMPACT::acquire::Statistics statistics( pDev_ );
        mvIMPACT::acquire::Request* pRequest = 0;
		mvIMPACT::acquire::Request* pPreviousRequest = nullptr;
        const unsigned int timeout_ms = 200;
		Ready = true;
        while( !boTerminated_ )
        {
            const int requestNr = pFI_->imageRequestWaitFor( timeout_ms );
            pRequest = pFI_->isRequestNrValid( requestNr ) ? pFI_->getRequest( requestNr ) : 0;
            if( pRequest )
            {
				if (pRequest->isOK())
				{
					// do something with the image
					int openCVDataType = CV_8UC1;
					if ((pRequest->imagePixelFormat.read() == ibpfBGR888Packed) || (pRequest->imagePixelFormat.read() == ibpfRGB888Packed))
						openCVDataType = CV_8UC3;
					cv::Mat openCVImage(cv::Size(pRequest->imageWidth.read(), pRequest->imageHeight.read()), openCVDataType, pRequest->imageData.read(), pRequest->imageLinePitch.read());
					cv::Mat image_clone = openCVImage.clone();
					if (!g_debug_mode)
					{
#ifdef IMM_PROCESS
						p_image_queue->put(std::make_pair(1,image_clone));	//放入临时队列
#else
						p_unit_queue->put(image_clone);	//放入临时队列
#endif
					}
					else
					{
						p_debug_queue->put(image_clone);	//放入调试队列
					}
					cnt++;
					// display some statistics
					if (cnt % 10 == 0)
					{
						QString data = QString::fromStdString(statistics.framesPerSecond.readS());
						emit updateStatistics(data.left(3),Local_Num);
					}
				}
				else
				{
					// some error: pRequest->requestResult.readS() will return a string representation
				}
				// this image has been used thus the buffer is no longer needed...
				if (pPreviousRequest)
				{
					// this image has been displayed thus the buffer is no longer needed...
					pPreviousRequest->unlock();
				}
				pPreviousRequest = pRequest;
				// send a new image request into the capture queue
				pFI_->imageRequestSingle();
            }
#if defined (IMM_FEED_BACK) || defined (CAP_FEED_BACK)
			m_threadFunc.SendFeedBack(ImageCap);
#endif
		}
        manuallyStopAcquisitionIfNeeded( pDev_, *pFI_ );
        if( pRequest )
        {
            pRequest->unlock();
        }
        pFI_->imageRequestReset( 0, 0 );
    }
    catch( const ImpactAcquireException& e )
    {
        emit error( QString::fromStdString( e.getErrorCodeAsString() ) );
    }
}

//-----------------------------------------------------------------------------
int CaptureThread::getPendingRequestNr( void )
//-----------------------------------------------------------------------------
{
    QMutexLocker lockedScope( &lock_ );
    int result = requestPendingForDisplay_;
    // Reset the ID of the request to tell the capture loop that this request has already been
    // picked up and someone else will take care of it from now on.
    requestPendingForDisplay_ = INVALID_ID;
    return result;
}