
#include "stdafx.h"
#include "MultiZebrasDemo.h"
#include "MultiZebrasDemoDlg.h"
#include "FileOpenCombo.h"
#include "afxdialogex.h"

#include "AppZebraScriptDemo.h"


LPTSTR lpAnsi2lpWChar(LPSTR lpstr);
LPSTR  lpWChar2lpAnsi(LPTSTR lptstr);

#ifndef ZEBRAZ4U3DLLWIN32_EXPORTS
#include "ZebraZ4U3DllWin32.h"
#include "ImageFmtExchg.h"
#else

#define __OPT_STREAMING_OFF__		0		// a picture captured by mipi when a KickoffRunStep called. 
#define __OPT_STREAMING_ON__		1		// pictures captured by mipi after a KickoffRunStep called.

typedef  void(*LOG_HOOK_FUNC)(int hZhandle, char *pszLogMsg, unsigned long logCbArg);

int SearchingRegisterFiles(__HZHANDLE__ hZhandle, char *pScriptName, LOG_HOOK_FUNC log_cbFunc, unsigned long logCbArg);
int LoadRegisterFiles(__HZHANDLE__ hZhandle, char *pRegFilesDir, LOG_HOOK_FUNC log_cbFunc, unsigned long logCbArg);
int RunTestStepFile(__HZHANDLE__ hZhandle, char *pTestStepName, int nOption);
void SetZebraSetting(__HZHANDLE__ hZhandle, char *pZebraSetting);
int RunRegisterFile(__HZHANDLE__ hZhandle, char *pRegisterName, int nOption);
int getRunStepstate(__HZHANDLE__ hZhandle, PSRUNSTEPSTATE pRunStepState);
int GrabImageRequest(__HZHANDLE__ hZhandle, short imgStartIndx, short imgEndIndx, unsigned char imgGotOpCode, unsigned char bWaitSnapped);
ULONG getPicture2Buffer(__HZHANDLE__ hZhandle, unsigned char *pPicBuffer, ULONG pPicBufSiz, UCHAR *errCode);
__PZEBRA_BOARD_INFO__ getZebraBoardInfo(__HZHANDLE__ hZhandle, TCHAR **pUsbPortName);

#endif

typedef struct
{
	char imgSavName[256];
	FILE *logFile;
	LONG ljustMilliSeconds;
	DWORD RunStepStatePollingTime;
	char szLastRunRegistFile[128];

} __sScriptLocVariables__, *__psScriptLocVariables__;

static __sScriptLocVariables__ scriptCntrlArg[__ZebraAppMax__ + 1];

////////////////////////////////////////////////////////////////////////////////////////////
// __loadRegisterSetting_external__ is option for testing SearchingRegisterFiles() setup in script file.

//#define __loadRegisterSetting_external__

/* comment code: "//" or '#' */
char* isSkipScriptCommentOrWhiteLine(char *chLineData, int sizOfBuf)
{
	char *pData = chLineData;
	char *pCmt, *pLast = chLineData + sizOfBuf;
	int i;

	while (*pData && *pData <= 0x20 && pData < pLast) pData++;

	if (*pData == 0 || pData >= pLast) return NULL;

	if ('/' == pData[0] && '/' == pData[1] || pData[0] == '#') return NULL;

	// Truncate the comments section ...
	pCmt = (char *)memchr(pData, '/', sizOfBuf - (pData - chLineData));
	if (pCmt && *(pCmt + 1) == '/')
	{
		do
		{
			*pCmt++ = 0x0;
		} while (pCmt < pLast);
	}
	i = strlen(pData) - 1;

	while (pData[i] <= 0x20) pData[i--] = 0x0;

	return pData;
}

char *getScriptFuncName(char *pzScriptLine, char **pzArgs)
{
	char *pArg, *pTmp;

	while (*pzScriptLine <= 0x20) pzScriptLine++;

	pArg = pTmp = (char *)memchr((char *)pzScriptLine, '(', strlen(pzScriptLine));

	if (pTmp)
	{
		if (pTmp) pTmp--;

		while (pTmp != pzScriptLine && *pTmp <= 0x20) pTmp--;
		pTmp++;
		*pTmp = 0x0;

		// Handle arguments
		pArg++;
		while (*pArg <= 0x20) pArg++;
		pTmp = (char *)memchr((char *)pArg, ')', strlen(pArg));

		if (pTmp)
		{
			*pTmp = 0x0;
			while (pArg != pTmp && *pTmp <= 0x20) pTmp--;
			pTmp++;
			*pTmp = 0x0;
		}

		*pzArgs = pArg;
	}
	return pzScriptLine;
}

//static char imgSavName[256];
void SaveImage2File(char *imageSav2File, int myId)
{
	strcpy(scriptCntrlArg[myId].imgSavName, imageSav2File);
}




//static FILE *logFile = NULL;
//static LONG ljustMilliSeconds = 0;
void myLogfunc(int hZhandle, char *logPrintOutString, unsigned long logCbArg)
{
	SYSTEMTIME	LocalTime;
	LONG deltaMilliSeconds = 0;
	int myId = (int)logCbArg;

	if (scriptCntrlArg[myId].logFile)
	{
		LONG ldayMilliSeconds;

		GetLocalTime(&LocalTime);
		ldayMilliSeconds = LocalTime.wHour * 60 * 60 * 1000 + LocalTime.wMinute * 60 * 1000 + LocalTime.wSecond * 1000 + LocalTime.wMilliseconds;

		if (scriptCntrlArg[myId].ljustMilliSeconds)
			deltaMilliSeconds = ldayMilliSeconds - scriptCntrlArg[myId].ljustMilliSeconds;

		scriptCntrlArg[myId].ljustMilliSeconds = ldayMilliSeconds;
		fprintf(scriptCntrlArg[myId].logFile, "%02d:%02d:%02d.%03d(dt:%d)=>%s", LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds, deltaMilliSeconds, logPrintOutString);
	}
}

void EnableLogFunc(char *logFileName, LOG_HOOK_FUNC LogHookFunc, unsigned long logCbArg)
{
	int myId = (int)logCbArg;
	if (LogHookFunc)
	{
		// Open log file
		scriptCntrlArg[myId].logFile = fopen(logFileName, "a");
		scriptCntrlArg[myId].ljustMilliSeconds = 0;
	}
	else
	{
		if (scriptCntrlArg[myId].logFile) fclose(scriptCntrlArg[myId].logFile);
		scriptCntrlArg[myId].logFile = NULL;
	}
}

#define		__key_Begin__					"Begin"
#define		__key_End__						"End"

#define		__key_SearchingRegisterFiles__	"SearchingRegisterFiles"
#define     __key_LoadRegisterFiles__		"LoadRegisterFiles"
#define		__key__RunTestStepFile__		"RunTestStepFile"
#define		__key__SetZebraSetting__		"SetZebraSetting"
#define		__key__RunRegisterFile__		"RunRegisterFile"

#define		__key__SaveImag2File__			"SaveImage2File"
#define		__key__GrabImage__				"GrabImage"
#define		__key__GrabImageAvg__			"GrabImageAvg"
#define		__key__RunStepStatePollingTime__ "RunStepStatePollingTime"
#define		__key_log__						"Log"
#define		__key_StreamingMode__			"StreamingMode"

//static DWORD RunStepStatePollingTime = 100;
//static char szLastRunRegistFile[128];

void ZebraScriptSimulateDemo(void *pThis, __HZHANDLE__ hZhandle, int myId, TCHAR *pScriptName, int *nTestStepsCnt, int bDontSaveImg)
{
	UCHAR		errCode;
	CMultiZebrasDemoDlg *pMain = (CMultiZebrasDemoDlg *)pThis;
	char 		*pszBuf = NULL;
	FILE		*fileScript = NULL;
//	HANDLE		hScript;	// for CreateFile 

	TCHAR		drive[_MAX_DRIVE];
	TCHAR		dir[_MAX_DIR];
	TCHAR		fname[_MAX_FNAME];
	TCHAR		ext[_MAX_EXT];
	TCHAR		szScriptMsg[MAX_PATH];
	BOOL		bScriptFuncOn = FALSE;
	BOOL        bscriptRaw8To10;
	int			StreamOnOff = __OPT_STREAMING_OFF__;
	__PZEBRA_BOARD_INFO__ pZebraBoardInfo;
	pZebraBoardInfo = getZebraBoardInfo(hZhandle, NULL);

	pszBuf = lpWChar2lpAnsi(pScriptName);

	_wsplitpath(pScriptName, drive, dir, fname, ext);
	wsprintf(szScriptMsg, L"Execute script: processing script \"%s%s\"...", fname, ext);
	pMain->UpdateProgressMsg(myId, 10, szScriptMsg);

	bscriptRaw8To10 = (pMain->m_scriptchkRaw8To10.GetCheck() == BST_CHECKED);

	scriptCntrlArg[myId].RunStepStatePollingTime = 100;
	scriptCntrlArg[myId].ljustMilliSeconds = 0;
	scriptCntrlArg[myId].logFile = NULL;
#ifdef __loadRegisterSetting_external__

	EnableLogFunc("ZebraTest.log", myLogfunc, (unsigned long)myId);

	*nTestStepsCnt = SearchingRegisterFiles(hZhandle, pszBuf, myLogfunc, (unsigned long)myId);

	pMain->UpdateProgressMsg(myId, -1, L"Execute script: download register-files");

	LoadRegisterFiles(hZhandle, NULL, myLogfunc, (unsigned long)myId);
	pMain->UpdateRunStepCmbList(hZhandle, myId);

	EnableLogFunc("", NULL, (unsigned long)myId);
#endif

	/*  if you use open the script file; please make sure let it could be shared with next open.
	SearchingRegisterFiles(...) function would open it again!
	*/
	//	if ((hScript = CreateFileA(pszBuf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) && 
	//		 hScript != INVALID_HANDLE_VALUE)
	if (fileScript = fopen(pszBuf, "rt"))
	{
		unsigned char	rdSettingBuffer[256];
		char            szScriptName[256];
		char            szFullPathArgScript[256];

		strcpy(szScriptName, pszBuf);	// save scriptName when SearchingRegisterFiles() hasn't set script file name 
		free(pszBuf);	// lpWChar2lpAnsi allocated buffer to be free

		// get every string line
		while (fgets((char *)rdSettingBuffer, sizeof(rdSettingBuffer), fileScript))
		{
			// Check USB disconnected!
			if (pZebraBoardInfo->nZebraStatus != __Zebra_Open_usable__)
			{
				pMain->MessageBox(L"*** Zebra USB disconnected! ***\r\n     Script is broken!");
				EnableLogFunc("", NULL, 0);
				break;
			}

			if ((pszBuf = isSkipScriptCommentOrWhiteLine((char *)rdSettingBuffer, sizeof(rdSettingBuffer))) == 0)
				continue;		// comment line 

			if (strcmp(__key_Begin__, pszBuf) == 0)	// in begin section start
			{
				bScriptFuncOn = TRUE;
				continue;
			}
			else if (strcmp(__key_End__, pszBuf) == 0)	// end section
			{
				EnableLogFunc("", NULL, (unsigned long)myId);
				bScriptFuncOn = FALSE;
				continue;
			}

			if (bScriptFuncOn)
			{
				char *pzArgs;
				char *pScripFuncName = getScriptFuncName(pszBuf, &pzArgs);

				if (strcmp(__key_SearchingRegisterFiles__, pScripFuncName) == 0)
				{
#ifndef __loadRegisterSetting_external__
					// This SearchingRegisterFiles() & LoadRegisterFiles() may put external of script file.
					// call them before open script file to collect used setting files in script

					if (*pzArgs == 0)
						pzArgs = szScriptName;
					else
					{
						char		drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];

						_splitpath(pzArgs, drive, dir, fname, ext);
						if (*drive == 0 && *dir == 0)
						{
							// appends arArgs file with script file path 
							// get script file directory path
							_splitpath(szScriptName, drive, dir, fname, ext);
							// make full path name
							_makepath(szFullPathArgScript, drive, dir, pzArgs, NULL);
							pzArgs = szFullPathArgScript;
						}

					}

					LPTSTR pzwArgs;
					wsprintf(szScriptMsg, L"Execute script: searching \"%s\"...", pzwArgs = lpAnsi2lpWChar(pzArgs));
					pMain->UpdateProgressMsg(myId, 20, szScriptMsg);
					free(pzwArgs);

					*nTestStepsCnt = SearchingRegisterFiles(hZhandle, pzArgs, myLogfunc, (unsigned long) myId);
#endif
					continue;
				}
				else if (strcmp(__key_LoadRegisterFiles__, pScripFuncName) == 0)
				{
#ifndef __loadRegisterSetting_external__
					// This LoadRegisterFiles() && SearchingRegisterFiles() may put external of script file.
					// call them before open script file to collect used setting files in script
					pMain->UpdateProgressMsg(myId, 30, L"Execute script: download register-files");

					LoadRegisterFiles(hZhandle, NULL, myLogfunc, myId);
					pMain->UpdateRunStepCmbList(hZhandle, myId);
#endif
					continue;
				}
				else if (strcmp(__key__RunTestStepFile__, pScripFuncName) == 0)
				{
					char szLogBuffer[256];
					LPTSTR pzwArgs;
					SRUNSTEPSTATE	sRunResult;

					// Run the register file
					wsprintf(szScriptMsg, L"Execute script: run test step file \"%s\"", pzwArgs = lpAnsi2lpWChar(pzArgs));
					pMain->UpdateProgressMsg(myId, 40, szScriptMsg);

					sprintf(szLogBuffer, "RunTestStepFile() run test step %s\n", pzArgs);
					strcpy(scriptCntrlArg[myId].szLastRunRegistFile, pzArgs);
					myLogfunc(hZhandle, szLogBuffer, (unsigned long)myId);

					RunTestStepFile(hZhandle, pzArgs, StreamOnOff);
					free(pzwArgs);
					getRunStepstate(hZhandle, &sRunResult);	// remove default status, 141014
					continue;
				}
				else if (strcmp(__key__SetZebraSetting__, pScripFuncName) == 0)
				{
					// Set Zebra setting for read Register file
					SetZebraSetting(hZhandle, pzArgs);
					continue;
				}
				else if (strcmp(__key__RunRegisterFile__, pScripFuncName) == 0)
				{
					char szLogBuffer[256];
					LPTSTR pzwArgs;
					SRUNSTEPSTATE	sRunResult;

					// Run the register file
					wsprintf(szScriptMsg, L"Execute script: run register file \"%s\"", pzwArgs = lpAnsi2lpWChar(pzArgs));
					pMain->UpdateProgressMsg(myId, 40, szScriptMsg);

					sprintf(szLogBuffer, "RunRegisterFile() run test step %s\n", pzArgs);
					strcpy(scriptCntrlArg[myId].szLastRunRegistFile, pzArgs);
					myLogfunc(hZhandle, szLogBuffer, (unsigned long) myId);

					RunRegisterFile(hZhandle, pzArgs, StreamOnOff);
					free(pzwArgs);
					getRunStepstate(hZhandle, &sRunResult);	// remove default status, 141014
					continue;
				}
				else if (strcmp(__key__SaveImag2File__, pScripFuncName) == 0)
				{
					LPTSTR pzwArgs;
					wsprintf(szScriptMsg, L"Execute script:  Image be saved to \"%s\"", pzwArgs = lpAnsi2lpWChar(pzArgs));
					pMain->UpdateProgressMsg(myId, 40, szScriptMsg);

					SaveImage2File(pzArgs, myId);
					free(pzwArgs);
					continue;
				}
				else if (strcmp(__key__GrabImage__, pScripFuncName) == 0)
				{
					int imgIndx, nRet;
					char saveFile[256];
					SYSTEMTIME	LocalTime;
					SRUNSTEPSTATE	sRunResult;
					UCHAR *pPic;
					ULONG  uPicGotSiz;

					char szLogBuffer[256];
					LPTSTR pzwArgs;

					// get which index image be got
					sscanf(pzArgs, "%d", &imgIndx);

					// save up the save file name
					GetLocalTime(&LocalTime);
					sprintf(saveFile, "%s~%s~%02d%02d-%02d%02d%02d.%03d_id#%d.raw", scriptCntrlArg[myId].imgSavName, scriptCntrlArg[myId].szLastRunRegistFile, LocalTime.wMonth, LocalTime.wDay, LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds, imgIndx);

					//wsprintf(szScriptMsg, L"Execute script:  get image save to \"%s\"", lpAnsi2lpWChar(saveFile));
					//pMain->UpdateProgressMsg(myId, -1, szScriptMsg);
					pMain->UpdateProgressMsg(myId, 60, L"Execute script:  Checking image is ready to get");

					// Check the get image is ready now!
					myLogfunc(hZhandle, "getRunStepstate() to get image state\n", myId);
					while ((nRet = getRunStepstate(hZhandle, &sRunResult)) > 0)
					{
						/* if (sRunResult.runResultState == __Sta_step_snapping__)
						sRunResult.resultType == __AppendData__
						sRunResult.appDataLen = 2;
						sRunResult.appendBuffer [0] = how many image are snapped
						sRunResult.appendBuffer [1] = has snapped images count
						*/
						if (sRunResult.runResultState == __Sta_None_Imgage__)
						{
							// error, no image pic is snapped
							pMain->UpdateProgressMsg(myId, 100, L"Execute script:  None_Imgage");

							sprintf(szLogBuffer, "getRunStepstate() - None_Imgage\n");
							myLogfunc(hZhandle, szLogBuffer, myId);
							return;
						}
						else if (sRunResult.runResultState == __Sta_step_snapping__ && sRunResult.resultType == __AppendData__)
						{
							// sRunResult.appendBuffer [0] --- picture count
							// sRunResult.appendBuffer [1] --- snapped pictured count

							if (sRunResult.appendBuffer[0] <= imgIndx)	// error index
							{
								pMain->UpdateProgressMsg(myId,70, L"Execute script:  snapping...");

								sprintf(szLogBuffer, "getRunStepstate() - request image id#%d > total image count(%d)\n", imgIndx, sRunResult.appendBuffer[0]);
								myLogfunc(hZhandle, szLogBuffer, (unsigned long)myId);
								return;
							}
#if 0	// remove 141017 - when just run-step get many pictures, but only get 1 or few pictures and run other run-step
							// would make state to invalid!
							if (sRunResult.appendBuffer[1] >= imgIndx)
							{
								sprintf(szLogBuffer, "getRunStepstate() - still snapping, but request id#%d is ready\n", imgIndx);
								myLogfunc(hZhandle, szLogBuffer, myId);
								break;
							}
							else
							{
								sprintf(szLogBuffer, "getRunStepstate() - request image id#%d not ready now\n", imgIndx);
								myLogfunc(hZhandle, szLogBuffer, myId);
								Sleep(scriptCntrlArg[myId].RunStepStatePollingTime);
								continue;
							}
#endif
						}
						else if (sRunResult.runResultState == __Sta_step_succeed__ && sRunResult.resultType == __SnapPicture__)
						{
							// sRunResult.snapCnt = g_snappedPicCnt;									// simulate a snap count
							// sRunResult.pSnaPicSiz[i] = size of every picture
							sprintf(szLogBuffer, "getRunStepstate() - images snapped succeed\n");
							myLogfunc(hZhandle, szLogBuffer, myId);
							break;
						}
						else if (sRunResult.runResultState == __Sta_Invalid__)
						{
							sprintf(szLogBuffer, "getRunStepstate() - images invalid\n");
							myLogfunc(hZhandle, szLogBuffer, myId);
							goto InvalContinue;
						}
					}	// while to check image ready

					wsprintf(szScriptMsg, L"Execute script:  Get image (%d) ", imgIndx);
					pMain->UpdateProgressMsg(myId, 90, szScriptMsg);

					// Send command to Zebra to get this image
// GrabImageAvg					if (strcmp(__key__GrabImage__, pScripFuncName) == 0)
// GrabImageAvg					{
						GrabImageRequest(hZhandle, imgIndx, imgIndx, __Grab_opt_noneOperation__, 1);	//	only get assigned index only and wait

						sprintf(szLogBuffer, "GrabImageRequest() - image#%d ~ image#%d raw image with wait\n", imgIndx, imgIndx);
						myLogfunc(hZhandle, szLogBuffer, (unsigned long) myId);
// GrabImageAvg					}
// GrabImageAvg					else if (strcmp(__key__GrabImageAvg__, pScripFuncName) == 0)
// GrabImageAvg					{
// GrabImageAvg						GrabImageRequest(hZhandle, imgIndx, imgIndx, __Grab_opt_ImageAvg__, 1);		//	only get assigned index only and wait
// GrabImageAvg
// GrabImageAvg						sprintf(szLogBuffer, "GrabImageRequest() - image#%d ~ image#%d raw images avrage with wait\n", imgIndx, imgIndx);
// GrabImageAvg						myLogfunc(hZhandle, szLogBuffer, myId);
// GrabImageAvg					}

					// Get image to buffer and then save it to file
					if (sRunResult.runResultState == __Sta_step_succeed__)
						pPic = (UCHAR *)malloc(sRunResult.pSnaPicSiz[imgIndx]);
					else
					{
						sRunResult.pSnaPicSiz[imgIndx] = 1024 * 1024 * 40;
						pPic = (UCHAR *)malloc(sRunResult.pSnaPicSiz[imgIndx]);		// make a maximum buffer to received data
					}

					sprintf(szLogBuffer, "getPicture2Buffer() - start\n");
					myLogfunc(hZhandle, szLogBuffer, myId);

					uPicGotSiz = getPicture2Buffer(hZhandle, pPic, sRunResult.pSnaPicSiz[imgIndx], &errCode);

					sprintf(szLogBuffer, "getPicture2Buffer() - end\n");
					myLogfunc(hZhandle, szLogBuffer, myId);

					if (__Error_getPicBufferTooShort == errCode)
					{
						sprintf(szLogBuffer, "getPicture2Buffer() - buffer too short error\n");
						myLogfunc(hZhandle, szLogBuffer, myId);
						//free(pPic);
						//continue;
					}
					if (bDontSaveImg)	// without save to file; only test for USB speed!
					{
						if (uPicGotSiz != sRunResult.pSnaPicSiz[imgIndx])
						{
							sprintf(szLogBuffer, "getPicture2Buffer() - data length error\n");
							myLogfunc(hZhandle, szLogBuffer, myId);
						}
						free(pPic);
						continue;
					}

					wsprintf(szScriptMsg, L"Execute script:  save image (%d) to \"%s\"", imgIndx, pzwArgs = lpAnsi2lpWChar(saveFile));
					pMain->UpdateProgressMsg(myId, 95, szScriptMsg);
					
					// Save got picture to file
					HANDLE hFile = CreateFileA(saveFile, // open One.txt
						GENERIC_WRITE,             // open for reading
						0,                        // do not share
						NULL,                     // no security
						CREATE_ALWAYS,            // existing file only
						FILE_ATTRIBUTE_NORMAL,    // normal file
						NULL);                    // no attr. template

					if (bscriptRaw8To10)
					{
						UCHAR *pPicRaw10;
						ULONG  uRaw10Size;
						int     errExchg;

						pPicRaw10 = RawStrmToRaw10(pPic, uPicGotSiz, &uRaw10Size, &errExchg);
						if (errExchg == __NO_ERROR_EXCHG__)
						{
							if (hFile != INVALID_HANDLE_VALUE)
							{
								DWORD wrLen;
								WriteFile(hFile, pPicRaw10, uRaw10Size, &wrLen, NULL);
								CloseHandle(hFile);
							}
							freeRawExchgBuffer(pPicRaw10);
						}
					}
					else
					{
						if (hFile != INVALID_HANDLE_VALUE)
						{
							DWORD wrLen;
							WriteFile(hFile, pPic, uPicGotSiz, &wrLen, NULL);
							CloseHandle(hFile);
						}
					}
					free(pPic);
					free(pzwArgs);
				InvalContinue:
					continue;
				}
				else if (strcmp(__key__GrabImageAvg__, pScripFuncName) == 0)
				{
					char *p;
					char szLogBuffer[256];
					__psOneZebraAppPrams__ pMyGrabArg = &pMain->m_sZebraUI[myId];

					// Check image-count of current test-step
					sscanf(pzArgs, "%d", &pMyGrabArg->nGrabStart);
					p = strchr(pzArgs, ',');
					if (p) p++;
					if (p < (pzArgs + strlen(pzArgs)))
					{
						int   ic, nPrtage;
						int	  errExchg;
						char saveFile[256];
						SYSTEMTIME	LocalTime;
						UCHAR *pPicRaw10_0 = NULL, *pPicRaw10_X;
						USHORT *pwPicRaw10_0 = NULL, *pwPicRaw10_X;
						ULONG uRaw10Siz0, uRaw10SizX;
						DWORD dwAvgStartTick, dRet;
						SRUNSTEPSTATE	sRunResult;

						sscanf(p, "%d", &pMyGrabArg->nGrabLast);

						// save up the save file name
						GetLocalTime(&LocalTime);
						sprintf(saveFile, "%s~%s~%02d%02d-%02d%02d%02d.%03d_id#%d-%d.raw", scriptCntrlArg[myId].imgSavName, scriptCntrlArg[myId].szLastRunRegistFile, LocalTime.wMonth, LocalTime.wDay, LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds, pMyGrabArg->nGrabStart, pMyGrabArg->nGrabLast);

						wsprintf(szScriptMsg, L"Execute script:  is that average-image ready to get?");
						pMain->UpdateProgressMsg(myId, 5, szScriptMsg);

						nPrtage = 95 / (pMyGrabArg->nGrabLast - pMyGrabArg->nGrabStart);

						sprintf(szLogBuffer, "GrabImageAvg() - starting\n");
						myLogfunc(hZhandle, szLogBuffer, myId);
						dwAvgStartTick = GetTickCount();

						// Kick grab thread to receive image
						pMyGrabArg->GrabAct = __GRAB_IMG_ACT_GOING__;
						SetEvent(pMyGrabArg->hGrabThrdCmd);

						for (ic = 0; ic < (pMyGrabArg->nGrabLast - pMyGrabArg->nGrabStart + 1); ic++)
						{
							// Wait image got!
							WaitForSingleObject(pMyGrabArg->hGrabThrdRslt, INFINITE);
							switch (pMyGrabArg->nGrabbeResult)
							{
							case __GRAB_IMG_GOT__:
								if (ic)
								{
									pPicRaw10_X = RawStrmToRaw10(pMyGrabArg->pGrabBuffer[pMyGrabArg->nQueTail],
										pMyGrabArg->dwImageSize[pMyGrabArg->nQueTail], &uRaw10SizX, &errExchg);
									pwPicRaw10_X = (USHORT *)pPicRaw10_X;

									for (int n = 0; n < uRaw10SizX / 2; n++)	// word adding
										pwPicRaw10_0[n] += pwPicRaw10_X[n];
									freeRawExchgBuffer(pPicRaw10_X);
								}
								else
								{
									pPicRaw10_0 = RawStrmToRaw10(pMyGrabArg->pGrabBuffer[pMyGrabArg->nQueTail],
										pMyGrabArg->dwImageSize[pMyGrabArg->nQueTail], &uRaw10Siz0, &errExchg);
									pwPicRaw10_0 = (USHORT *)pPicRaw10_0;
								}

								free(pMyGrabArg->pGrabBuffer[pMyGrabArg->nQueTail]);
								pMyGrabArg->nQueTail++;
								if (pMyGrabArg->nQueTail >= __GRAB_IMAGE_BUFFER_COUNT__) pMyGrabArg->nQueTail = 0;
								break;
							default:
								goto ErrGrabbed;
								;
							}
							
							wsprintf(szScriptMsg, L"Execute script:  Get average image (%d) ", ic);
							pMain->UpdateProgressMsg(myId, 5 + ic*(nPrtage+1), szScriptMsg);

						}	// for all images

						for (int n = 0; n < uRaw10Siz0 / 2; n++)	// average
							pwPicRaw10_0[n] /= (pMyGrabArg->nGrabLast - pMyGrabArg->nGrabStart + 1);

						sprintf(szLogBuffer, "GrabImageAvg() - end; GrabeImageAvg() total ticks=%d\n", GetTickCount() - dwAvgStartTick);
						myLogfunc(hZhandle, szLogBuffer, myId);

						// Save average file
						wsprintf(szScriptMsg, L"Execute script:  save average image (%d-%d) to \"%s\"", pMyGrabArg->nGrabStart, pMyGrabArg->nGrabLast, lpAnsi2lpWChar(saveFile));
						pMain->UpdateProgressMsg(myId, 98, szScriptMsg);

						// Save got picture to file
						HANDLE hFile = CreateFileA(saveFile, // open One.txt
							GENERIC_WRITE,             // open for reading
							0,                        // do not share
							NULL,                     // no security
							CREATE_ALWAYS,            // existing file only
							FILE_ATTRIBUTE_NORMAL,    // normal file
							NULL);                    // no attr. template

						if (hFile != INVALID_HANDLE_VALUE)
						{
							DWORD wrLen;
							WriteFile(hFile, pPicRaw10_0, uRaw10Siz0, &wrLen, NULL);
							CloseHandle(hFile);
						}
						freeRawExchgBuffer(pPicRaw10_0);

					ErrGrabbed:
						// make sure just run state is completed!
						while ((dRet = getRunStepstate(hZhandle, &sRunResult)) > 0)
						{
							if (sRunResult.runResultState != __Sta_step_snapping__)
								break;
						}
					}
				}
				else if (strcmp(__key_log__, pScripFuncName) == 0)
				{
					EnableLogFunc(pzArgs, myLogfunc, (unsigned long)myId);
					continue;
				}
				else if (strcmp(__key__RunStepStatePollingTime__, pScripFuncName) == 0)
				{
					sscanf(pzArgs, "%d", &scriptCntrlArg[myId].RunStepStatePollingTime);
					continue;
				}
				else if (strcmp(__key_StreamingMode__, pScripFuncName) == 0)
				{
					if (*pzArgs == '1')
						StreamOnOff = __OPT_STREAMING_ON__;
					else
						StreamOnOff = __OPT_STREAMING_OFF__;
					continue;
				}

			}
		}	// while - parsing

		fclose(fileScript);
		//		CloseHandle(hScript);
	}
	else
		free(pszBuf);	// lpWChar2lpAnsi allocated buffer to be free
	//
	pMain->UpdateProgressMsg(myId, 100, L"Execute script: done!");

}


DWORD WINAPI GetImageThread(LPVOID Arg)
{
	CMultiZebrasDemoDlg *pMain = (CMultiZebrasDemoDlg *)Arg;
	int		myId = pMain->m_SelectIndx;
	__psOneZebraAppPrams__ pMyGrabArg = &pMain->m_sZebraUI[myId];
	__HZHANDLE__ hZhandle = pMyGrabArg->m_AppZebraHandle;

	// Signal caller this thread is enabled!
	SetEvent(pMain->hThrdStartEvt);

	while (TRUE)
	{
		DWORD dRet;
		if ((dRet = WaitForSingleObject(pMyGrabArg->hGrabThrdCmd, INFINITE)) == WAIT_OBJECT_0)
		{
			char	szLogBuffer[256];
			wchar_t	strScriptMsg[256];
			SRUNSTEPSTATE	sRunResult;
			int		imgIndx, iQueNxtIndx;
			UCHAR	errCode;

			if (pMyGrabArg->bGrabExit) break;

			hZhandle = pMyGrabArg->m_AppZebraHandle;

			switch (pMyGrabArg->GrabAct)
			{
			case __GRAB_IMG_ACT_GOING__:

//				wsprintf(strScriptMsg, L"Execute script:  is that average-image ready to get?");
//				pMain->UpdateProgressMsg(myId, 5, strScriptMsg);

//				nPrtage = 95 / (pMyGrabArg->nGrabLast - pMyGrabArg->nGrabStart);
				for (imgIndx = pMyGrabArg->nGrabStart; imgIndx <= pMyGrabArg->nGrabLast; imgIndx++)
				{
					// Check the get image is ready now!
					myLogfunc(hZhandle, "getRunStepstate() to get average image state\n", myId);
					while ((dRet = getRunStepstate(hZhandle, &sRunResult)) > 0)
					{
						/* if (sRunResult.runResultState == __Sta_step_snapping__)
						sRunResult.resultType == __AppendData__
						sRunResult.appDataLen = 2;
						sRunResult.appendBuffer [0] = how many image are snapped
						sRunResult.appendBuffer [1] = has snapped images count
						*/
						if (sRunResult.runResultState == __Sta_None_Imgage__)
						{
							// error, no image pic is snapped
//							::PostMessage(hwndProgress, WM_MIPI_PROGRESS_MONITOR, IDC_PROGRESS_DOT, (LPARAM)L"Execute Script");
//							::ShowWindow(hwndProgress, SW_HIDE);

							sprintf(szLogBuffer, "getRunStepstate() - None average Imgage\n");
							myLogfunc(hZhandle, szLogBuffer, myId);

							pMyGrabArg->nGrabbeResult = __GRAB_IMG_NON_PIC__;
							ReleaseSemaphore(pMyGrabArg->hGrabThrdRslt, 1, NULL);
							goto endGrabbing;
						}
						else if (sRunResult.runResultState == __Sta_step_snapping__ && sRunResult.resultType == __AppendData__)
						{
							// sRunResult.appendBuffer [0] --- picture count
							// sRunResult.appendBuffer [1] --- snapped pictured count

							if (sRunResult.appendBuffer[0] <= pMyGrabArg->nGrabStart)	// error index
							{
//								::PostMessage(hwndProgress, WM_MIPI_PROGRESS_MONITOR, IDC_PROGRESS_DOT, (LPARAM)L"Execute Script");
//								::ShowWindow(hwndProgress, SW_HIDE);

								sprintf(szLogBuffer, "getRunStepstate() - request average image id#%d > total image count(%d)\n", imgIndx, sRunResult.appendBuffer[0]);
								myLogfunc(hZhandle, szLogBuffer, myId);

								pMyGrabArg->nGrabbeResult = __GRAB_IMG_START_INDX_TOO_LOW__;
								ReleaseSemaphore(pMyGrabArg->hGrabThrdRslt, 1, NULL);
								goto endGrabbing;;
							}
							else if (sRunResult.appendBuffer[0] <= pMyGrabArg->nGrabLast)	// error index
							{
//								::PostMessage(hwndProgress, WM_MIPI_PROGRESS_MONITOR, IDC_PROGRESS_DOT, (LPARAM)L"Execute Script");
//								::ShowWindow(hwndProgress, SW_HIDE);

								sprintf(szLogBuffer, "getRunStepstate() - request average image id#%d > total image count(%d)\n", imgIndx, sRunResult.appendBuffer[0]);
								myLogfunc(hZhandle, szLogBuffer, myId);

								pMyGrabArg->nGrabbeResult = __GRAB_IMG_LAST_INDX_OVER__;
								ReleaseSemaphore(pMyGrabArg->hGrabThrdRslt, 1, NULL);
								goto endGrabbing;;
							}
							if (sRunResult.appendBuffer[1] >= imgIndx)
							{
								sprintf(szLogBuffer, "getRunStepstate() - still snapping, but request average image id#%d is ready\n", imgIndx);
								myLogfunc(hZhandle, szLogBuffer, myId);
								break;
							}
							else
							{
								sprintf(szLogBuffer, "getRunStepstate() - request average image id#%d not ready now\n", imgIndx);
								myLogfunc(hZhandle, szLogBuffer, myId);
								Sleep(80);
								continue;
							}
						}
						else if (sRunResult.runResultState == __Sta_step_succeed__ && sRunResult.resultType == __SnapPicture__)
						{
							if (sRunResult.snapCnt <= pMyGrabArg->nGrabStart)	// error index
							{
//								::PostMessage(hwndProgress, WM_MIPI_PROGRESS_MONITOR, IDC_PROGRESS_DOT, (LPARAM)L"Execute Script");
//								::ShowWindow(hwndProgress, SW_HIDE);

								sprintf(szLogBuffer, "getRunStepstate() - request average image id#%d > total image count(%d)\n", imgIndx, sRunResult.appendBuffer[0]);
								myLogfunc(hZhandle, szLogBuffer, myId);

								pMyGrabArg->nGrabbeResult = __GRAB_IMG_START_INDX_TOO_LOW__;
								ReleaseSemaphore(pMyGrabArg->hGrabThrdRslt, 1, NULL);
								goto endGrabbing;;
							}
							else if (sRunResult.snapCnt <= pMyGrabArg->nGrabLast)	// error index
							{
//								::PostMessage(hwndProgress, WM_MIPI_PROGRESS_MONITOR, IDC_PROGRESS_DOT, (LPARAM)L"Execute Script");
//								::ShowWindow(hwndProgress, SW_HIDE);

								sprintf(szLogBuffer, "getRunStepstate() - request average image id#%d > total image count(%d)\n", imgIndx, sRunResult.appendBuffer[0]);
								myLogfunc(hZhandle, szLogBuffer, myId);

								pMyGrabArg->nGrabbeResult = __GRAB_IMG_LAST_INDX_OVER__;
								ReleaseSemaphore(pMyGrabArg->hGrabThrdRslt, 1, NULL);
								goto endGrabbing;;
							}
							// sRunResult.snapCnt = g_snappedPicCnt;									// simulate a snap count
							// sRunResult.pSnaPicSiz[i] = size of every picture
							sprintf(szLogBuffer, "getRunStepstate() - grab average images snapped succeed\n");
							myLogfunc(hZhandle, szLogBuffer, myId);
							break;
						}
						else if (sRunResult.runResultState == __Sta_Invalid__)
						{
							sprintf(szLogBuffer, "getRunStepstate() - grab average images invalid\n");
							myLogfunc(hZhandle, szLogBuffer, myId);

							pMyGrabArg->nGrabbeResult = __GRAB_IMG_RUN_STEP_ERR__;
							ReleaseSemaphore(pMyGrabArg->hGrabThrdRslt, 1, NULL);
							goto endGrabbing;
						}
					}	// while to check image ready

//					wsprintf(strScriptMsg, L"Execute script:  Get average image (%d) ", imgIndx);
//					pMain->UpdateProgressMsg(myId, 5 + imgIndx*nPrtage, strScriptMsg);

					GrabImageRequest(hZhandle, imgIndx, imgIndx, __Grab_opt_noneOperation__, 1);	//	only get assigned index only and wait

					// Get image to buffer and then save it to file
					if (sRunResult.runResultState == __Sta_step_succeed__)
						pMyGrabArg->pGrabBuffer[pMyGrabArg->nQueHead] = (UCHAR *)malloc(sRunResult.pSnaPicSiz[imgIndx]);
					else
					{
						sRunResult.pSnaPicSiz[imgIndx] = 1024 * 1024 * 40;
						pMyGrabArg->pGrabBuffer[pMyGrabArg->nQueHead] = (UCHAR *)malloc(sRunResult.pSnaPicSiz[imgIndx]);		// make a maximum buffer to received data
					}

					sprintf(szLogBuffer, "getPicture2Buffer() - average image start\n");
					myLogfunc(hZhandle, szLogBuffer, myId);

					pMyGrabArg->dwImageSize[pMyGrabArg->nQueHead] = getPicture2Buffer(hZhandle, pMyGrabArg->pGrabBuffer[pMyGrabArg->nQueHead], sRunResult.pSnaPicSiz[imgIndx], &errCode);

					sprintf(szLogBuffer, "getPicture2Buffer() - average image end\n");
					myLogfunc(hZhandle, szLogBuffer, myId);

					if (__Error_getPicBufferTooShort == errCode)
					{
						sprintf(szLogBuffer, "getPicture2Buffer() - buffer too short error\n");
						myLogfunc(hZhandle, szLogBuffer, myId);
						//free(pPic);
						//continue;
					}

					pMyGrabArg->nGrabbeResult = __GRAB_IMG_GOT__;
					ReleaseSemaphore(pMyGrabArg->hGrabThrdRslt, 1, NULL);

					pMyGrabArg->nQueHead++;
					if (pMyGrabArg->nQueHead == __GRAB_IMAGE_BUFFER_COUNT__)pMyGrabArg->nQueHead = 0;
					while (pMyGrabArg->nQueHead == pMyGrabArg->nQueTail)
					{
						Sleep(100);	// Wait buffer free
					}
				}	// for - image pictures
			endGrabbing:
				break;

			default:
				;
			}
		}
	}
	return 0;
}
