// Test.cpp : Defines the entry point for the console application.
//
#define _CRT_SECURE_NO_WARNINGS

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#include <time.h>
#include <Windows.h>
#include <direct.h>

#include "L_Types.h"
#include "LoadBmp.cpp"

const char dir1[]="ean_upc\\";
const char* files[] =
{
	"im1.bmp"
	,"c128.bmp"
	,"c39.bmp"
	,"cb.bmp"
	,"il2-5.bmp"
	,"EAN8.bmp"
	,"im2.bmp"
	,NULL   // last member of array must be NULL
};

void WaitEndUser();

void printLINEAR_QUALITY(LINEAR_QUALITY lq)
{
	 printf("\nGrades for the scan reflectance profile\n");
	 printf("Parameter    Value   Grade          Average Grade on ten scannings\n");
	 printf("Decode                 %d                     %6.2f\n", (int)lq.decode_grad, lq.decode_grad_av);
	 printf("Rmax         %6.2f%%                           \n", lq.max_reflectance);
	 printf("Rmin         %6.2f%%   %d                     %6.2f\n", lq.min_reflectance, (int)lq.min_reflectance_grad, lq.min_reflectance_grad_av);
	 printf("SC           %6.2f%%   %d                     %6.2f\n", lq.symbol_contrast, (int)lq.symbol_contrast_grad, lq.symbol_contrast_grad_av);
	 printf("ECmin        %6.2f%%   %d                     %6.2f\n", lq.min_edge_contrast, (int)lq.min_edge_contrast_grad, lq.min_edge_contrast_grad_av);
	 printf("MOD          %6.2f    %d                     %6.2f\n", lq.modulation, (int)lq.modulation_grad, lq.modulation_grad_av);
	 printf("Defects      %6.2f    %d                     %6.2f\n", lq.defects, (int)lq.defects_grad, lq.defects_grad_av);
	 printf("Decodability %6.2f    %d                     %6.2f\n", lq.decodability, (int)lq.decodability_grad, lq.decodability_grad_av);
	 printf("Overall Grade          %d                     %6.2f\n", (int)lq.overall_grade_grad, lq.overall_grade_grad_av);
}

void printLINEAR_SCAN_LINE(int idx_scan_line, LINEAR_SCAN_LINE* sl)
{

	printf("\nResult for the ten scan reflectance profile\n");
	printf(" N start_x  start_y  end_x  end_y  q_zone  c_sum  length  data\n");
	for (int i = 0; i < 10; i++)
	{
		if (i != idx_scan_line)
			printf(" %d %6d  %7d  %5d  %5d  %6d  %5d  %5d   %s\n", i,
				sl[i].scan_line_start_x,
				sl[i].scan_line_start_y,
				sl[i].scan_line_end_x,
				sl[i].scan_line_end_y,
				sl[i].quietzone,
				sl[i].checksum,
				sl[i].length,
				sl[i].dataRes);
		else
			printf(" %d * %4d * %6d * %4d * %4d * %5d * %4d * %4d * %s\n", i,
				sl[i].scan_line_start_x,
				sl[i].scan_line_start_y,
				sl[i].scan_line_end_x,
				sl[i].scan_line_end_y,
				sl[i].quietzone,
				sl[i].checksum,
				sl[i].length,
				sl[i].dataRes);
	}
}

 
int main(int argc, char **argv)
{
	int result;   int  row;
	int rowcount, colcount;
	int maxR = 4000; int maxC = 4000;
	TRow*    pbits;
	TRow     pmembits;  // Image in Memory
	int ResLoadBMP;
	int lq, i;

	int   countFalse = 0;
	int   csumErr = 0, confErr = 0, qzErr = 0, countOK = 0;
	char  dir[MAX_PATH];
	char  path[MAX_PATH];
	PL_Decoder    pDecoder;
	PL_Options    pDecWithOpt;
	TL_ImageInfo* pl_imageinfo;
	TL_Info*      pl_info;
	int stat[19][5];
	
	strcpy(dir, ".\\");
	strcat(dir, dir1);

	pDecoder = Connect_L_Decoder(maxR, maxC);
	if (pDecoder == NULL) return 0;

	pmembits = (TRow)malloc(maxR*maxC);       //  Image in Memory
	pbits = (TRow*)malloc(maxR * sizeof(TRow)); // pointers to ScanLines

	for (row = 0; row < maxR; row++) {
		pbits[row] = &pmembits[maxC*row];
	}


	TL_OptMode opt1 = { 1,//10,  // int maxLcount;
					   -1,  // int typecode any;
					   // TCM_TCODE39 | TCM_TEAN13EX,    //0x200, // Code128
					   // 4,  // interleaved
					   // 5,  // EAN13
					   // 8,  // int typecode PN;
					   // 9,  // int typecode IMB;
					   // 17,  // int typecode TADF;
					   // 10, // PHARMACODE
					   // TCM_TRSS_ALL,
					   // 14,
					   // TC_TNZP,

						0,  // int timeout;
						1,  // int paramq;
						0,  // int checksum_I25;
						0,  // int checksum_C39;
					   -1,  // int quietzone;
						 0,//1, // int smartmode
						 0, // int EC_Factor
						 0, // int pharmacodedir
						 2, //int scandir = vertical+horizontal;
						 8, //int scanstep;
						 0, // checksum_CB;
						 0, // int FullASCII_C39;
						-1, // 250,  //int colbeg
						-1, // 440,  //int colend      //200, 50, 440, 430
						-1, //  50,  //int rowbeg
						-1, // 430,  //int rowend
					   // 50  // TADF_num
						99,  // TADF_num
					   // 65,  // TADF_num
						L_DEFAULT // L_WHITE 
	};

	pDecWithOpt = Create_L_Options(pDecoder, opt1);

	// Setting advanced options.
	// OFF when decoding, replace the code UPCE with UPCA by adding zeros. 
	//Set_L_Addition_Option(pDecWithOpt, L_OPT_EXT_UPCE_TO_UPCA, 0);

	// OFF a quiet zone for the pharmacode is required.
	//Set_L_Addition_Option(pDecWithOpt, L_OPT_PHARMACODE_QUEIT_ZONE_MANDATORY, 0);

	long currTime1 = 0;

	printf("maxLcount=%d \n", opt1.maxLcount);
	printf("typecode=%d \n", opt1.typecode);
	printf("timeout=%d \n", opt1.timeout);
	printf("paramq=%d \n", opt1.paramq);
	printf("checksum_I25=%d \n", opt1.checksum_I25);
	printf("checksum_C39=%d \n", opt1.checksum_C39);
	printf("checksum_CB=%d \n", opt1.checkSum_CB);
	printf("quietzone=%d \n", opt1.quietzone);
	printf("smartmode=%d \n", opt1.smartmode);
	printf("FullASCII=%d \n", opt1.FullASCII_C39);
	printf("scandir=%d \n", opt1.scandir);
	printf("scanstep=%d \n", opt1.scanstep);
	printf("TADF_num=%d \n", opt1.TADF_num);

	int count = 0;
	double TotalTime = 0.0;

	for (i = 0; i < 19; i++)
		memset(stat[i], 0, sizeof stat[0]);

	for (int j = 0; files[j] != NULL; j++)
	{
		strcpy(path, dir);
		strcat(path, files[j]);

		printf("\n");
		printf("%s ", path);
		rowcount = maxR;
		colcount = maxC;
		ResLoadBMP = LoadBMP(path, pbits, rowcount, colcount);

		if (ResLoadBMP != 0)
		{
			printf("ResLoadBMP == %d \n", ResLoadBMP);
			continue;
		}

		count++;

		LARGE_INTEGER liFreq;
		LARGE_INTEGER liStart;
		LARGE_INTEGER liStop;
		double m_DecodeTime;
		::QueryPerformanceFrequency(&liFreq);
		::QueryPerformanceCounter(&liStart); // Do your processing

		result = Decode_L_Bits(pDecWithOpt, rowcount, colcount, pbits);

		::QueryPerformanceCounter(&liStop);
		LONGLONG llTimeDiff = liStop.QuadPart - liStart.QuadPart;
		m_DecodeTime = (double)llTimeDiff * 1000 / liFreq.QuadPart;
		printf(",  time=%7.2f", m_DecodeTime);
		TotalTime += m_DecodeTime; // /1000

		if (result < 0)
		{
			printf(" decoder == NULL!!!!!!");
			return 0;
		}
		pl_imageinfo = GetL_ImageInfo(pDecWithOpt);
		lq = pl_imageinfo->LCount;
		printf(" %d", lq);

		if (lq > 0)
		{
			for (i = 0; i <= lq - 1; i++)
			{
				pl_info = GetL_Info(pDecWithOpt, i);
				printf("\n      ");
				switch (pl_info->type)
				{
				case TC_TCODE128: printf(" C128:   ");
					break;
				case TC_TCODE39: printf(" C39:    ");
					break;
				case TC_TCODABAR: printf(" Cbar:   ");
					break;
				case TC_TINTERLEAVED: printf(" Il 2/5: ");
					break;
				case TC_TEAN13: printf(" EAN13:  ");
					break;
				case TC_TEAN8: printf(" EAN8:   ");
					break;
				case TC_TUPCE: printf(" UPCE:   ");
					break;
				case TC_TEAN13EX: printf(" EAN13_ADDON:  ");
					break;
				case TC_TUPCEEX: printf(" UPCE_ADDON:   ");
					break;
				case TC_TPHARMACODE: printf(" Pharma: ");
					break;
				case TC_TADF: printf(" TADF, barcount=%d   ", pl_info->add_lq->actTADFnum);
					break;
				default: printf(" Unknown:");
				};

				if (pl_info->pch[-3] == ']')
				{
					printf(" %c%c%c :", pl_info->pch[-3], pl_info->pch[-2], pl_info->pch[-1]);
				}
				printf(" %d * %s ", pl_info->pchlen, pl_info->pch);

				if (pl_imageinfo->BreakReason == L_TIMEOUT)
					printf("== TIMEOUT! ");

				if ((pl_info->type) > 0) {
					int bt, rr
						, n = 0;
					bt = pl_info->type;
					if (bt < 0 || bt>19)
						bt = 16; // Other
					rr = pl_info->RejectionReason;
					if (rr == L_SUCCESSFUL) n = 1;
					else if (rr == L_CHECKSUM_FAILED) n = 2;
					else if (rr == L_NOT_CONFIRMED) n = 3;
					else if (rr == L_NOT_QUIET_ZONE) n = 4;
					stat[bt - 1][n] += 1;
				}
				if (pl_info->RejectionReason == L_CHECKSUM_FAILED)
				{
					csumErr++;
					printf("=CS!");
				}
				if (pl_info->RejectionReason == L_NOT_CONFIRMED)
				{
					confErr++;
					printf("=Nc!");
				}
				if (pl_info->RejectionReason == L_NOT_QUIET_ZONE)
				{
					qzErr++;
					printf("=QZ!");
				}
				if (pl_info->RejectionReason == L_SUCCESSFUL)
				{
					countOK++;
					printf("=OK!");
				}
				//  printLINEAR_QUALITY(pl_info->lq);
				//  printLINEAR_SCAN_LINE(pl_info->idx_scan_line, pl_info->sl);

				// Label rect
				/*
				for (int ii = 0; ii < 8; ii++)
				{
					printf(" * %d ", (int)pl_info->rowcols[ii]);
					}
					*/
			}
		}
		else
		{
			countFalse++;
			switch (pl_imageinfo->BreakReason)
			{
			case L_TIMEOUT:  printf("=== TO! ");
				continue;
			}
			switch (pl_imageinfo->RejectionReason)
			{
			case L_NO_LINEAR_FOUND:  printf("=== NF!");
				continue;
			case L_POOR_IMAGE_QUALITY:  printf("=== Poor Qual!");
				break;
			case L_RR_UNKNOWN:   printf("=====   Unknown error !");
				break;
			}

		}
	}

	char ct[13];
	printf("\n\n");
	printf("             !  OK ,  CS , Conf,  QZ \n");
	printf("-------------------------------------\n");
	for (i = 1; i < 19; i++)
	{
		switch (i) {
		case 1: strcpy(ct, "CODE128     ");
			break;
		case 2: strcpy(ct, "CODE39      ");
			break;
		case 3: strcpy(ct, "CODABAR     ");
			break;
		case 4: strcpy(ct, "INTERLEAVED ");
			break;
		case 5: strcpy(ct, "EAN13       ");
			break;
		case 6: strcpy(ct, "EAN8        ");
			break;
		case 7: strcpy(ct, "UPCE        ");
			break;
		case 8: strcpy(ct, "POSTNET     ");
			break;
		case 9: strcpy(ct, "IMB         ");
			break;
		case 10: strcpy(ct, "PHARMACODE  ");
			break;
		case 11: strcpy(ct, "RSS         ");
			break;
		case 12: strcpy(ct, "RSS_L       ");
			break;
		case 13: strcpy(ct, "RSS_E       ");
			break;
		case 14: strcpy(ct, "EAN13 addon ");
			break;
		case 15: strcpy(ct, "UPCE addon  ");
			break;
		case 17: strcpy(ct, "TADF        ");
			break;
		case 18: strcpy(ct, "NZP         ");
			break;
		case 19: strcpy(ct, "SuissPost   ");
			break;
		default: strcpy(ct, "            ");
			break;
		}
		if (i >= 1)
			printf("%s !%4d ,%4d ,%4d ,%4d \n"
				, ct, stat[i - 1][1], stat[i - 1][2], stat[i - 1][3], stat[i - 1][4]);
	}
	printf("\n count=%d,  decoded=%d,  countFalse=%d  \n", count, count - countFalse, countFalse);
	printf("\n SUCCESSFUL=%d, NOT_QUIET_ZONE=%d, CHECKSUM_FAILED=%d, NOT_CONFIRMED=%d \n",
		countOK, qzErr, csumErr, confErr
	);
	if (count > 0)
		printf(",  avr. time = %8.2f\n", TotalTime / count);

	Delete_L_Options(pDecWithOpt);
	Disconnect_L_Decoder(pDecoder);

	free(pbits);
	free(pmembits);

	WaitEndUser();
}

void WaitEndUser()
{
	char ch;
	printf("\nPrint 'Enter' to exit>\n");
	scanf("%c", &ch);
}
