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

//#include "stdafx.h"
#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 "L_Types_DLL_BWR.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 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("Rs_ECmin     %6.2f%%                         \n",lq.Rs_ECmin);
//  printf("Rb_ECmin     %6.2f%%                         \n",lq.Rb_ECmin);
  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("ERNmax       %6.2f%%                       \n",lq.ERNmax);
  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);
  }
 }

 void WaitEndUser();


extern "C" void MainTask_Fn(void)
{

  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];
  HINSTANCE dllinstance;
//  WCHAR WDIR[MAX_PATH];

  TConnect_L_Decoder         Connect_L_Decoder;
  TDisconnect_L_Decoder      Disconnect_L_Decoder;
  TCreate_L_Options          Create_L_Options;
  TDelete_L_Options          Delete_L_Options;
  TDecode_L_Bits             Decode_L_Bits;
  TGetL_ImageInfo            GetL_ImageInfo;
  TGetL_Info                 GetL_Info;

//   dllinstance = LoadLibrary(L"..\\LC_PRO.dll");
   dllinstance = LoadLibrary(L"LC_PRO.dll");

	if (dllinstance == NULL)
	{
		printf("Failed load the library!");
		void WaitEndUser();
		return;
	}

   //strcpy(dir,"..\\");
   strcpy(dir,".\\");
   strcat(dir,dir1);

   Connect_L_Decoder    = (TConnect_L_Decoder    )GetProcAddress(dllinstance,"Connect_L_Decoder");
   Disconnect_L_Decoder = (TDisconnect_L_Decoder )GetProcAddress(dllinstance,"Disconnect_L_Decoder");
   Create_L_Options     = (TCreate_L_Options     )GetProcAddress(dllinstance,"Create_L_Options");
   Delete_L_Options     = (TDelete_L_Options     )GetProcAddress(dllinstance,"Delete_L_Options");
   Decode_L_Bits        = (TDecode_L_Bits        )GetProcAddress(dllinstance,"Decode_L_Bits");
   GetL_ImageInfo       = (TGetL_ImageInfo       )GetProcAddress(dllinstance,"GetL_ImageInfo");
   GetL_Info            = (TGetL_Info            )GetProcAddress(dllinstance,"GetL_Info");

	if (Connect_L_Decoder == NULL)
	{
		printf("Failed read poiners to the functions of the library!");
		void WaitEndUser();
		return;
   }
     

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

  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);

  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);



//  printf("dir=%s \n",dir1);



  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 ", files[j]);
   printf("%s ", path);
   rowcount = maxR;
   colcount = maxC;
   ResLoadBMP = LoadBMP (path , pbits ,rowcount ,colcount);

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

   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 ;
   }
   pl_imageinfo = GetL_ImageInfo(pDecWithOpt);
   lq = pl_imageinfo->LCount;
   printf(" %d",lq);
//   printf(" LCount=%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);

       //  for(int ii=0; ii<8; ii++)  printf(" * %d ", (int)pl_info->rowcols[ii]);
     }  // for i
   }else {  // lq==0
     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);
}

int main(int argc, char **argv)
{
   MainTask_Fn();
   return 0;
}
