using Emgu.CV;
using Emgu.CV.Structure;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZXing;

namespace ETC2019.Models.Barcode.Linear
{
    public class Code39
    {
        public DateTime CreateDT { get; set; }   // 資料建立時間
        public DateTime ModifyDT { get; set; }   // 資料修改時間
        public CodePattern[] Items { get; set; } // 資料集合
        public string Decode(Bitmap image)
        {
            return Method2(image);
        }

        public string Method1(Bitmap image)
        {
            Dictionary<string, Dictionary<string, string>> code = new Dictionary<string, Dictionary<string, string>>();

            Image<Bgr, byte> bgr = new Image<Bgr, byte>(image);

            Image<Gray, byte> gray = bgr.Convert<Gray, byte>();

            CvInvoke.Threshold(gray, gray, 0, 255, Emgu.CV.CvEnum.ThresholdType.Otsu);

            int h = gray.Rows, w = gray.Cols, start = 0, end = w, position = 0;

            int[] row = new int[w];

            string result = string.Empty;

            foreach (CodePattern pattern in Items)
                if (code.ContainsKey(pattern.Space))
                {
                    if (!code[pattern.Space].ContainsKey(pattern.Bar))
                        code[pattern.Space].Add(pattern.Bar, pattern.Char);
                }
                else
                    code.Add(pattern.Space, new Dictionary<string, string>() { { pattern.Bar, pattern.Char } });

            for (int x = 0; x < w / 2; x++)
                for (int y = 0; y < h; y++)
                {
                    if (gray.Data[y, x, 0] == 0 && start == 0)
                        start = x;
                    if (gray.Data[y, w - x - 1, 0] == 0 && end == w)
                        end = w - x - 1;
                }

            for (int x = 0; x < w; x++)
            {
                row[x] = gray.Data[h / 2, x, 0];

                row[x] = row[x] > 0 ? 1 : 0;
            }

            while (position < w)
            {
                string bars = string.Empty, spaces = string.Empty;

                int white = 0, black = 0;

                if (row[position] == 0)
                {
                    while ((bars.Length < 5 || spaces.Length < 4) && position < w)
                    {
                        if (row[position] == 0)
                        {
                            if (white > ((end - start) / (9 * 11)))
                            {
                                spaces = spaces + "1";

                                white = 0;
                            }
                            if (white > 0)
                            {
                                spaces = spaces + "0";

                                white = 0;
                            }
                            black = black + 1;
                        }
                        else
                        {
                            if (black > ((end - start) / (9 * 11)))
                            {
                                bars = bars + "1";

                                black = 0;
                            }
                            if (black > 0)
                            {
                                bars = bars + "0";

                                black = 0;
                            }
                            white = white + 1;
                        }
                        position = position + 1;
                    }
                    result = result + (code.ContainsKey(spaces) ? code[spaces].ContainsKey(bars) ? code[spaces][bars] : "?" : "?");
                }
                else { position = position + 1; }
            }
            return result;
        }

        public string Method2(Bitmap image)
        {
            BarcodeReader reader = new BarcodeReader();

            //Image<Bgr, byte> bgr = new Image<Bgr, byte>(image);

            //Image<Gray, byte> gray = bgr.Convert<Gray, byte>();

            //CvInvoke.Threshold(gray, gray, 0, 255, Emgu.CV.CvEnum.ThresholdType.Otsu);

            return reader.Decode(image)?.Text;
        }
    }
}
