#include <iostream>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <dmtx.h>

using namespace cv;
using namespace std;


int main()
{
   DmtxImage      *img;
   DmtxDecode     *dec;
   DmtxRegion     *reg;
   DmtxMessage    *msg;
   

//    Mat cv_img = imread("/home/luis/Documentos/Dissertação/Codigo/Leitura de DataMatrix/Imagens/wikidmtx_dmg2.jpg",CV_LOAD_IMAGE_GRAYSCALE);
//    Mat cv_img = imread("/home/luis/Documentos/Dissertação/Codigo/Leitura de DataMatrix/minhadmtx_dmg6.jpg",CV_LOAD_IMAGE_GRAYSCALE);
//    Mat cv_img = imread("/home/luis/Documentos/Dissertação/Codigo/Leitura de DataMatrix/Imagens/mydmtx.png",CV_LOAD_IMAGE_GRAYSCALE);
   Mat cv_img = imread("/home/luis/Documentos/Dissertação/Codigo/Aquisição de Imagem/Imagens/Imagem3.jpeg",CV_LOAD_IMAGE_COLOR);
   
//    int type = cv_img.type();
//    int depth = cv_img.depth();
//    int chan = cv_img.channels();
//    cout << "Tipo: " << type << ", Depth: " << depth << ", channels: " << chan << endl;
//    
   
//    cout << "Size: " << cv_img.size() << endl;
//    cout << "Flags: " << cv_img.flags

   cv::Mat gray_img;
   cvtColor(cv_img, gray_img, CV_BGR2GRAY, 0);
   
   img = dmtxImageCreate(gray_img.data, gray_img.cols, gray_img.rows, DmtxPack8bppK);
   assert(img != NULL);

   dec = dmtxDecodeCreate(img, 1);
   assert(dec != NULL);

//    For single matrix reading =========================================================
   
//    Matriz a cores apenas lê a DmtxPack24bppRGB e leva 18 ms no minimo a ler a Imagem0
//    Matriz a grayscale lê mais rápido com DmtxPack8bppK e leva 14 ms no minimo a ler a Imagem0
   
   
   DmtxTime delay = dmtxTimeAdd(dmtxTimeNow(),500);
   reg = dmtxRegionFindNext(dec, &delay);
   while(reg != NULL) {
      msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined);
      if(msg != NULL) {
//          fputs("output: \"", stdout);
//          fwrite(msg->output, sizeof(unsigned char), msg->outputIdx, stdout);
	 cout << "output: " << msg->output << endl;
// 	 cout << "Código completo: " << msg->codeSize << endl;
//          fputs("\"\n", stdout);
         dmtxMessageDestroy(&msg);
      }


      int height = cv_img.rows-1;
      cv::circle(cv_img, cv::Point (reg->leftLoc.X, height - reg->leftLoc.Y), 10, CV_RGB(255,0,0));
      cv::circle(cv_img, cv::Point (reg->rightLoc.X, height - reg->rightLoc.Y), 10, CV_RGB(255,0,0));
      cv::circle(cv_img, cv::Point (reg->topLoc.X, height - reg->topLoc.Y), 10, CV_RGB(255,0,0));
      cv::circle(cv_img, cv::Point (reg->bottomLoc.X, height - reg->bottomLoc.Y), 10, CV_RGB(255,0,0));
//       cv::circle(cv_img, cv::Point(10, height-10), 10, CV_RGB(255,0,0));
      
      reg = dmtxRegionFindNext(dec, &delay);
//       dmtxRegionDestroy(&reg);
   }
   imshow("DataMatrix",cv_img);
   
//    For multiple matrix reading =======================================================
//    DmtxTime* delay;
//    delay->sec = 10;
//    delay->usec = 0;
//    reg = dmtxRegionFindNext(dec, delay);
//    while(reg != NULL) {
//       msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined);
//       if(msg != NULL) {
//          fputs("output: \"", stdout);
//          fwrite(msg->output, sizeof(unsigned char), msg->outputIdx, stdout);
// // 	 cout << "output: " << msg->output << endl;
// // 	 cout << "Código completo: " << msg->codeSize << endl;
//          fputs("\"\n", stdout);
//          dmtxMessageDestroy(&msg);
//       }else{
// 	cout << "Matrix detectada. Mensagem não descodificada" << endl;
//       }
//       reg = dmtxRegionFindNext(dec, NULL);
// //    }else{
// //      cout << "Matrix não detectada" << endl;
//    }
   
   waitKey(0);
   dmtxRegionDestroy(&reg);
   dmtxDecodeDestroy(&dec);
   dmtxImageDestroy(&img);
   exit(0);

}
