#include <windows.h>
#define _interlockedbittestandset(a, b) _interlockedbittestandset(volatile long*, long)
#define _interlockedbittestandreset(a, b) _interlockedbittestandreset(volatile long*, long)
#define _interlockedbittestandset64(a, b) _interlockedbittestandset(volatile long long*, long long)
#define _interlockedbittestandreset64(a, b) _interlockedbittestandreset(volatile long long*, long long)
#include <intrin.h>
#undef _interlockedbittestandset
#undef _interlockedbittestandreset
#undef _interlockedbittestandset64
#undef _interlockedbittestandreset64

#include <tchar.h>
#include <stdio.h>

#include "../../../include/StTrgApi.h"

#ifdef _WIN64
#pragma comment(lib, "../../../lib/x64/StTrgApi.lib")
#else //_WIN64
#pragma comment(lib, "../../../lib/x86/StTrgApi.lib")
#endif //_WIN64

//OpenCV
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#ifdef _DEBUG
#define CV_LIBEXT "d.lib"
#else
#define CV_LIBEXT ".lib"
#endif
#define CV_LIB_FILE_NAME(MOD) MOD CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION) CV_LIBEXT
#pragma comment(lib, CV_LIB_FILE_NAME("opencv_core"))
#pragma comment(lib, CV_LIB_FILE_NAME("opencv_imgproc"))
#pragma comment(lib, CV_LIB_FILE_NAME("opencv_highgui"))

using namespace cv;

#define GRAB_COUNT 1000


//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	HANDLE hCamera = INVALID_HANDLE_VALUE;

	//-------------------------------------------------------------------------
	//Open
	//-------------------------------------------------------------------------
	hCamera = StTrg_Open();
	if(INVALID_HANDLE_VALUE == hCamera)
	{
		_tprintf(TEXT("Couldn't Open.\n"));
		return(-1);
	}

	//-------------------------------------------------------------------------
	//Transfer Start
	//-------------------------------------------------------------------------
	if(!StTrg_StartTransfer(hCamera))
	{
		_tprintf(TEXT("Couldn't Start.\n"));
		return(-1);
	}

	
	//-------------------------------------------------------------------------
	//Get ScanMode
	//-------------------------------------------------------------------------
	WORD  wScanMode;
	DWORD  dwOffsetX;
	DWORD  dwOffsetY;
	DWORD  dwWidth;
	DWORD  dwHeight;
	if(!StTrg_GetScanMode(hCamera, &wScanMode, &dwOffsetX, &dwOffsetY, &dwWidth , &dwHeight))
	{
		_tprintf(TEXT("Couldn't get ScanMode.\n"));
		return(-1);
	}

	//-------------------------------------------------------------------------
	//Get TransferBitsPerPixel
	//-------------------------------------------------------------------------
	DWORD  dwTransferBitsPerPixel;
	if(!StTrg_GetTransferBitsPerPixel(hCamera, &dwTransferBitsPerPixel))
	{
		_tprintf(TEXT("Couldn't get TransferBitsPerPixel.\n"));
		return(-1);
	}
	switch(dwTransferBitsPerPixel)
	{
	case(STCAM_TRANSFER_BITS_PER_PIXEL_RAW_08):
	case(STCAM_TRANSFER_BITS_PER_PIXEL_RAW_10):
	case(STCAM_TRANSFER_BITS_PER_PIXEL_RAW_12):
		break;
	default:
		_tprintf(TEXT("Not expected TransferBitsPerPixel value.\n"));
		return(-1);
	}
	
	//-------------------------------------------------------------------------
	//Get ColorArray
	//-------------------------------------------------------------------------
	WORD wColorArray = 0;
	if(!StTrg_GetColorArray(hCamera, &wColorArray))
	{
		_tprintf(TEXT("Couldn't get ColorArray.\n"));
		return(-1);
	}

	int nInputType = CV_8UC1;
	switch(dwTransferBitsPerPixel)
	{
	case(STCAM_TRANSFER_BITS_PER_PIXEL_RAW_10):
	case(STCAM_TRANSFER_BITS_PER_PIXEL_RAW_12):	nInputType = CV_16UC1; break;
	}
	Mat inputMat(dwHeight, dwWidth, nInputType);

	if(!inputMat.isContinuous())
	{
		_tprintf(TEXT("inputMat is invalid.\n"));
		return(-1);
	}
	PBYTE pbyteRaw = inputMat.ptr(0);
	DWORD dwBufferSize = inputMat.rows * inputMat.cols * inputMat.elemSize() * inputMat.channels();

	int nConvert = 0;
	switch(wColorArray)
	{
	case(STCAM_COLOR_ARRAY_RGGB):	nConvert = CV_BayerRG2RGB;	break;
	case(STCAM_COLOR_ARRAY_GRBG):	nConvert = CV_BayerGR2RGB;	break;
	case(STCAM_COLOR_ARRAY_GBRG):	nConvert = CV_BayerGB2RGB;	break;
	case(STCAM_COLOR_ARRAY_BGGR):	nConvert = CV_BayerBG2RGB;	break;
	}
	//-------------------------------------------------------------------------
	//
	//-------------------------------------------------------------------------
	Mat displayMat;
	for(size_t i = 0; i < GRAB_COUNT; i++)
	{
		DWORD dwNumberOfBytesTrans = 0;
		DWORD dwFrameNo = 0;
		DWORD dwTimeout = 1000;
		if(!StTrg_TakeRawSnapShot(hCamera, pbyteRaw, dwBufferSize, &dwNumberOfBytesTrans, &dwFrameNo, dwTimeout))
		{
			_tprintf(TEXT("Couldn't take raw snap shot.\n"));
			return(-1);
		}
		_tprintf(TEXT("Recieved %u\r\n"), i);

		Mat *pMat = &inputMat;
		if(nConvert != 0)
		{
			cvtColor(inputMat, displayMat, nConvert);
			pMat = &displayMat;
		}
		imshow("Image1", *pMat);

		waitKey(30);
	}
	
	//-------------------------------------------------------------------------
	//Stop Transfer
	//-------------------------------------------------------------------------
	if(!StTrg_StopTransfer(hCamera))
	{
		_tprintf(TEXT("Can't Stop.\n"));
		return(-1);
	}

	//-------------------------------------------------------------------------
	//Close
	//-------------------------------------------------------------------------
	StTrg_Close(hCamera);
	
	return 0;
}

