//-----------------------------------------------------------------------------
#include "CaptureThread.h"
#include "PropViewFrame.h"
#include <wx/event.h>

using namespace std;
using namespace mvIMPACT::acquire;

unsigned int CaptureThread::m_activeInstance = 0;
unsigned int CaptureThread::m_instanceCnt = 0;

//-----------------------------------------------------------------------------
CaptureThread::CaptureThread( FunctionInterface* pFuncInterface, Device* pDev, wxWindow* pParentWindow ) : 
	wxThread( wxTHREAD_JOINABLE ), m_boLive(false), m_boRunning(false), m_currentRequest(INVALID_ID),
	m_discardedImages(0), m_instanceNr(m_instanceCnt++), m_nextPendingRequest(INVALID_ID),
	m_parentWindowID(pParentWindow->GetId()), m_pDev(pDev), m_pFuncInterface(pFuncInterface),  
	m_pParentWindowEventHandler(pParentWindow->GetEventHandler())	
//-----------------------------------------------------------------------------
{

}

//-----------------------------------------------------------------------------
CaptureThread::~CaptureThread( )
//-----------------------------------------------------------------------------
{ 
	m_boRunning = false;
	Wait();

	if( m_nextPendingRequest != INVALID_ID )
	{
		m_pFuncInterface->imageRequestUnlock( m_nextPendingRequest );
		m_nextPendingRequest = INVALID_ID;
	}

	if( m_currentRequest != INVALID_ID )
	{
		m_pFuncInterface->imageRequestUnlock( m_currentRequest );
		m_currentRequest = INVALID_ID;
	}
}

//-----------------------------------------------------------------------------
TRequestResult CaptureThread::GetImageData( ImageBufferDesc* pImgBufDesc, RequestInfo* pReqInfo, wxString& pixelFormat ) const
//-----------------------------------------------------------------------------
{
	wxCriticalSectionLocker locker(m_critSect);
	if( m_nextPendingRequest != INVALID_ID )
	{
		if( m_currentRequest != INVALID_ID )
		{
			m_pFuncInterface->imageRequestUnlock( m_currentRequest );
		}
		m_currentRequest = m_nextPendingRequest;
		m_nextPendingRequest = INVALID_ID;
	}

	if( m_currentRequest != INVALID_ID )
	{
		const Request* pReq = m_pFuncInterface->getRequest( m_currentRequest );
		if( pReq )
		{
			ImageBufferDesc nbd(pReq->getImageBufferDesc());
			*pImgBufDesc = nbd;
			//*pImgBufDesc = ImageBufferDesc(ib); // doesn't work with GCC...
			const RequestInfo& ri = pReq->getInfo();
			*pReqInfo = ri;
			pixelFormat = wxString(pReq->getParamS( irpPixelFormat ).c_str());
			return pReq->getResult().result;
		}
	}
	else
	{
		ImageBufferDesc nbd(1);
		*pImgBufDesc = nbd;
		//*pImgBufDesc = ImageBufferDesc(ib); // doesn't work with GCC...
		pixelFormat = "unknown";
		memset( pReqInfo, 0, sizeof(RequestInfo) );
		return rrOK;
	}
	return rrError;
}

//-----------------------------------------------------------------------------
void* CaptureThread::Entry()
//-----------------------------------------------------------------------------
{
	m_boRunning = true;
	while( m_boRunning )
	{
		int requestNr;
		if( m_boLive )
		{
			RequestImages();
		}
		if( ( requestNr = m_pFuncInterface->imageRequestWaitFor( 200, 0 ) ) >= 0 )
		{
			wxCriticalSectionLocker locker(m_critSect);
			if( m_pFuncInterface->isRequestNrValid( requestNr ) )
			{
				const Request* pReq = m_pFuncInterface->getRequest( requestNr );
				if( pReq )
				{
					if( m_activeInstance == m_instanceNr )
					{
						TRequestResult rr = pReq->getResult().result;
						if( rr == rrOK )
						{
							if( m_nextPendingRequest != INVALID_ID )
							{
								m_pFuncInterface->imageRequestUnlock( m_nextPendingRequest );
								++m_discardedImages;
								wxCommandEvent e( imageSkippedEvent, m_parentWindowID );
								wxPostEvent( m_pParentWindowEventHandler, e );
							}
							else
							{
								wxCommandEvent e( imageReadyEvent, m_parentWindowID );
								wxPostEvent( m_pParentWindowEventHandler, e );
							}
							m_nextPendingRequest = requestNr;

						}
						else
						{
							if( rr & rrUnprocessibleRequest )
							{
								m_lastErrorMessage = wxString(pReq->getParamS(irpResult).c_str());
							}
							m_pFuncInterface->imageRequestUnlock( requestNr );
							// Livemode is stopped depending on requestresult, TRequestResult
							if( rr & rrUnprocessibleRequest )
							{
								SetLiveMode( false );
								m_pFuncInterface->imageRequestReset( 0, 0 );
								wxCommandEvent e( liveModeAborted, m_parentWindowID );
								e.SetString(m_lastErrorMessage);
								wxPostEvent( m_pParentWindowEventHandler, e );
							}
						}
					}
					else
					{
						m_pFuncInterface->imageRequestUnlock( requestNr );
						++m_discardedImages;
					}
				}
			}			
		}
	}
	return 0;
}

//-----------------------------------------------------------------------------
int CaptureThread::ExchangeLastSnapResult( int newResult ) const
//-----------------------------------------------------------------------------
{
	wxCriticalSectionLocker locker( m_critSect );
	int oldval = m_currentRequest;
	m_currentRequest = newResult;
	return oldval;
}

//-----------------------------------------------------------------------------
int CaptureThread::GetLastSnapResult( void ) const
//-----------------------------------------------------------------------------
{
	return ExchangeLastSnapResult( INVALID_ID );
}

//-----------------------------------------------------------------------------
void CaptureThread::SetActive( void )
//-----------------------------------------------------------------------------
{
	wxCriticalSectionLocker locker( m_critSect );
	m_activeInstance = m_instanceNr;
}

//-----------------------------------------------------------------------------
int CaptureThread::SetLiveMode( bool boOn )
//-----------------------------------------------------------------------------
{
	wxCriticalSectionLocker locker( m_critSect );

	if( boOn )
	{
		m_pFuncInterface->imageRequestReset( 0, 0 );
		if( m_nextPendingRequest != INVALID_ID )
		{
			m_pFuncInterface->imageRequestUnlock( m_nextPendingRequest );
			m_nextPendingRequest = INVALID_ID;
		}

		m_discardedImages = 0;

		int result = RequestImages();
		if( result == 0 )
		{
			m_boLive = boOn;
		}
		else
		{
			wxMessageDialog dlg( NULL, wxString::Format( wxT("Live not started(Reason: %s)! More information can be found in the *.log-file or the debug output.\n"), ImpactAcquireException::getErrorCodeAsString(result).c_str() ), wxT("Error"), wxOK | wxICON_WARNING );
			dlg.ShowModal();
		}
	}
	else
	{
		m_boLive = boOn;
	}

	return m_boLive;
}

////-----------------------------------------------------------------------------
//int CaptureThread::SetLiveMode( bool boOn )
////-----------------------------------------------------------------------------
//{
//	wxCriticalSectionLocker locker( m_critSect );
//	m_boLive = boOn;
//	if( m_boLive )
//	{
//		RequestImages();
//		m_discardedImages = 0;
//	}
//	else
//	{
//		if( m_nextPendingRequest != INVALID_ID )
//		{
//			m_pFuncInterface->imageRequestUnlock( m_nextPendingRequest );
//			m_nextPendingRequest = INVALID_ID;
//		}
//	}
//	return m_boLive;
//}

//-----------------------------------------------------------------------------
int CaptureThread::RequestImages() 
//-----------------------------------------------------------------------------
{
	int result;
	int requestCnt=0;
	do
	{
		result = m_pFuncInterface->imageRequestSingle(0);
		if( result >= 0 )
		{
			++requestCnt;
		}
		else
		{
			break;
		}
	}
	while( 1 );

	if( requestCnt != 0 )
	{
		result = 0;
	}
	return result;
}
