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

namespace ETC_App1
{
    public class D1
    {
        public ROI ROI { get; set; } = new ROI();

        public static string JsonPath = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + Path.DirectorySeparatorChar + "data";

        public static D1 Load()
        {
            if (File.Exists(JsonPath + Path.DirectorySeparatorChar + "D1.json"))
            {
                StreamReader stream = new StreamReader(JsonPath + Path.DirectorySeparatorChar + "D1.json");

                D1 setting = JsonConvert.DeserializeObject<D1>(stream.ReadToEnd());

                stream.Close();

                return setting;
            }
            else { return new D1(); }
        }

        //public void Save()
        //{
        //    StreamWriter stream = new StreamWriter(JsonPath);

        //    stream.WriteLine(JsonConvert.SerializeObject(this));

        //    stream.Flush();

        //    stream.Close();
        //}

        public class Code39
        {
            public static Dictionary<string, Dictionary<string, string>> Decode = new Dictionary<string, Dictionary<string, string>>();

            public Code39()
            {
                Decode.Add("0100", new Dictionary<string, string>()
                {
                    { "10001", "1" },
                    { "01001", "2" },
                    { "11000", "3" },
                    { "00101", "4" },
                    { "10100", "5" },
                    { "01100", "6" },
                    { "00011", "7" },
                    { "10010", "8" },
                    { "01010", "9" },
                    { "00110", "0" },
                });
                Decode.Add("0010", new Dictionary<string, string>()
                {
                    { "10001", "A" },
                    { "01001", "B" },
                    { "11000", "C" },
                    { "00101", "D" },
                    { "10100", "E" },
                    { "01100", "F" },
                    { "00011", "G" },
                    { "10010", "H" },
                    { "01010", "I" },
                    { "00110", "J" },
                });
                Decode.Add("0001", new Dictionary<string, string>()
                {
                    { "10001", "K" },
                    { "01001", "L" },
                    { "11000", "M" },
                    { "00101", "N" },
                    { "10100", "O" },
                    { "01100", "P" },
                    { "00011", "Q" },
                    { "10010", "R" },
                    { "01010", "S" },
                    { "00110", "T" },
                });
                Decode.Add("1000", new Dictionary<string, string>()
                {
                    { "10001", "U" },
                    { "01001", "V" },
                    { "11000", "W" },
                    { "00101", "X" },
                    { "10100", "Y" },
                    { "01100", "Z" },
                    { "00011", "-" },
                    { "10010", "." },
                    { "01010", " " },
                    { "00110", "$" },
                });
                Decode.Add("1110", new Dictionary<string, string>()
                {
                    { "00000", "$" },
                });
                Decode.Add("1101", new Dictionary<string, string>()
                {
                    { "00000", "/" },
                });
                Decode.Add("1011", new Dictionary<string, string>()
                {
                    { "00000", "+" },
                });
                Decode.Add("0111", new Dictionary<string, string>()
                {
                    { "00000", "%" },
                });
            }

            public string ProcessMethod2(ROI roi, Bitmap bmp)
            {
                Rectangle rect = new Rectangle(roi.X, roi.Y, roi.Width, roi.Height);

                Image<Bgr, byte> bgr = new Image<Bgr, byte>(bmp.Clone(rect, bmp.PixelFormat));

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

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

                BarCodeReader reader = new BarCodeReader(gray.Bitmap);

                if (reader.Read())
                {
                    return reader.GetCodeText();
                }
                else
                {
                    return "";
                }

                //BarcodeResult result = BarcodeReader.ReadASingleBarcode(gray.Bitmap, BarcodeEncoding.Code128);

                //return result.Text;

                //BarcodeReader reader = new BarcodeReader();

                //reader.SetImage(bmp.Clone(rect, bmp.PixelFormat));

                //return "";

                //string barcode = BarcodeImaging.ReadBarcodes(gray.Bitmap, 0, gray.Bitmap.Size.Width, BarcodeImaging.ScanDirection.Horizontal, BarcodeImaging.BarcodeType.Code39);

                //return barcode;
            }

            public string ProcessMethod1(ROI roi, Bitmap bmp)
            {
                Rectangle rect = new Rectangle(roi.X, roi.Y, roi.Width, roi.Height);

                Image<Bgr, byte> bgr = new Image<Bgr, byte>(bmp.Clone(rect, bmp.PixelFormat));

                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;

                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 + (Decode.ContainsKey(spaces) ? Decode[spaces].ContainsKey(bars) ? Decode[spaces][bars] : "?" : "?");
                    }
                    else { position = position + 1; }
                }
                return result;
            }
        }
    }
}
