// mt_test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "nblib.h"
#include <iostream>
#include <fstream>

#define MAX_IP_ADDR_STRING 16
#define MAX_BOARD_WIDTH   1000

using namespace std;

ostream* g_stream;

HANDLE g_hEvent = INVALID_HANDLE_VALUE; // Global notification event;

/****************************************************************************************/
static BOOL getfactor(SCANNERPARAMS& factors, char * ipAddr)
    {
    FILE * inp;
	int res;
	factors.lead_spots  = 5;
    factors.lead_wait   = 4;
	factors.trail_spots = 5;
    factors.trail_wait  = 4;
    factors.history		= 0;
    factors.maxwidth	= MAX_BOARD_WIDTH;
    factors.maxreverse  = 25;
    factors.mode        = 0;
    factors.pcindex_trg = 0;
    factors.escale		= 0;
    factors.pcindex_len = 1;
    factors.segments    = 0;
	factors.trail_holdscan = 0;
	factors.pcindex_stopscan = 2;
	factors.timer_freq = 0;
    factors.encoder_mode = 0;

    inp = fopen("FACTOR.DAT","rt");
    if (inp)
        {
        res = fscanf(inp,"%s\n",ipAddr);
        if(strlen(ipAddr) < 7)
        {
            // factor.dat does not contain IP address....
            factors.lead_spots = atoi(ipAddr);
            strcpy(ipAddr,"0.0.0.0");
        }
        else
		{
            res = fscanf(inp,"%d\n",&factors.lead_spots);
		}

        fscanf(inp,"%d\n",&factors.lead_wait);
        fscanf(inp,"%d\n",&factors.trail_spots);
        fscanf(inp,"%d\n",&factors.trail_wait);
        fscanf(inp,"%d\n",&factors.history);
        fscanf(inp,"%d\n",&factors.maxwidth);
        fscanf(inp,"%d\n",&factors.maxreverse);
        fscanf(inp,"%d\n",&factors.mode);
        fscanf(inp,"%d\n",&factors.pcindex_trg);
        fscanf(inp,"%d\n",&factors.escale);
        fscanf(inp,"%d\n",&factors.pcindex_len);
        fscanf(inp,"%d\n",&factors.segments);
		fscanf(inp,"%d\n",&factors.trail_holdscan);
		fscanf(inp,"%d\n",&factors.pcindex_stopscan);
		fscanf(inp,"%d\n",&factors.timer_freq);
        fscanf(inp,"%d\n",&factors.encoder_mode);    
        fclose(inp);
        }
    return TRUE;
    }
/****************************************************************************************/
void print_scans(ostream& stream, SCANNEDOBJECTST* scans){
	if (scans == NULL)
		return;
	

    stream<<"Allocated lines:" << scans->allocatedlines <<endl;
	stream<< "First line:" << scans->firstscanline <<endl;
	stream<< "Last line:" << scans->lastscanline <<endl;
	stream<< "Valid lines:" << scans->validlines <<endl <<endl;

/*	for (int j = 0; j<scans->lastscanline-scans->firstscanline; j++){
		ONELINEST* st = &(scans->scanline[j]);
		stream<<"Encoder:"<<st->encoder<<endl;
		stream<<"PacketId:"<< st->packetid<<endl;
		for(int i =0 ; i<NB_MAXHEADS*NB_MAXSPOTS; i++){
			if(st->scanline[i]!=LMI_OUTRANGE)
				stream<<"\t" << st->scanline[i];
		}
		stream<<endl;
		stream.flush();
	}
*/
} 
/****************************************************************************************/
// event hadler thread routine
DWORD WINAPI  _notificationroutine(LPVOID data){
	int nBoardReadyNum = 0;
	
	// Allocate storage for scanned object
	SCANNEDOBJECTST* scans = (SCANNEDOBJECTST*) malloc(sizeof(SCANNEDOBJECTST)+sizeof(ONELINEST)*MAX_BOARD_WIDTH);
	while(g_hEvent!=INVALID_HANDLE_VALUE && scans != NULL){
		if(WAIT_OBJECT_0 == WaitForSingleObject(g_hEvent, INFINITE)){
			ASYNCEVENTST apt;
			apt.code = 0;
			apt.data = 0;
			nbGetLastAsyncEvent(&apt);
			switch(apt.code){
				case ASYNC_EVENT_CONNECTION_LOST:
					printf("Connection lost event\n");
					break;
				case ASYNC_EVENT_HEADS_CHANGED:
					printf("Heads changed event\n");
					break;
				case ASYNC_EVENT_BOARD_READY:
					printf("Board ready event #%d\n", nBoardReadyNum++);
					memset(scans, 0, sizeof(SCANNEDOBJECTST)+sizeof(ONELINEST)* MAX_BOARD_WIDTH);
                    scans->allocatedlines = MAX_BOARD_WIDTH;
					if(nbGetScannedObject(scans))
							print_scans(*g_stream, scans);
					break;
				case ASYNC_EVENT_LOG_PC_INFO:
					printf("pc info event\n");
					break;
				default:
					break;			
			}			
			ResetEvent(g_hEvent);
		}else{	
			break;
		}
	}
	if(scans!=NULL)
		free(scans);
	printf("Notofication thread finished: Invalid event handle\n"); 
	return 0;
};  
/****************************************************************************************/
bool OpenScanner()
{
	OPENSCANNERST openscannerst;
	SCANNERPARAMS scannerparams;
	char ipAddrString[MAX_IP_ADDR_STRING] = "0.0.0.0";
	openscannerst.nicIPAddress	= NULL;					//If NULL then searches network for IP
	openscannerst.hEvent		= g_hEvent;				//event handler for asynchronous events
	int nblib_version = 0;
	char nbfw_version[MINVERSIONSZ] = {0};
	int error = 0;
	const char **errorstr = 0;
	getfactor(scannerparams,ipAddrString);							//Gets scanner parameters from FACTOR.DAT
	if(!strcmp(ipAddrString,"0.0.0.0"))
	{
		openscannerst.IPAddress		= NULL;		//If NULL then searches network for IP
	}
	else
	{
		openscannerst.IPAddress		= ipAddrString;		//If NULL then searches network for IP
	}

	if(!nbOpenScanner(&openscannerst, &scannerparams))
	{	
		error = nbGetLastError((const char **)&errorstr);
		printf("ERROR %2d, Scanner not open\n %s ", error, errorstr);
		return false;
	}
	else
		printf("Connected to IP: %s ", openscannerst.IPAddress);

	if(!nbGetFwVersion(nbfw_version))
		printf("Can't get FW version");
	else
		printf("NPH FW version %s ",nbfw_version);

	nblib_version = nbGetVersion();
	printf("NbLib Version %d\n",nblib_version);	

	memset(&openscannerst, 0, sizeof(OPENSCANNERST) );
	memset(&scannerparams, 0, sizeof(SCANNERPARAMS) );
	return true;
};
/****************************************************************************************/
int main(int argc, char **argv, char **envp){
	g_stream = &cout;

	ofstream  fstr;

	if(argc>1 ){
		fstr.open((char*)argv[1]);
		g_stream= &fstr;
	}

	DWORD threadId = 0;
	HANDLE hThread = INVALID_HANDLE_VALUE;
	g_hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	hThread =  CreateThread(NULL,0,_notificationroutine,NULL,0,&threadId);
	OpenScanner();
	
	BXHEADANDSPOTDATA data[NB_MAXHEADS]={0};
	int numHeads = 0;
	nbGetSystemData(&data[0],&numHeads,8);
	
	WaitForSingleObject(hThread,INFINITE);	
	CloseHandle(hThread);
	nbCloseScanner();	
	CloseHandle(g_hEvent);
	g_hEvent = INVALID_HANDLE_VALUE;
	
	fstr.close();

	return 0;
}