using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
using System.Threading.Tasks;
using detect.gui.Models;
using detect.gui.VWMS;
using PaddleOCRSharp;
using Splat;

namespace detect.gui.Services;

public class OCRService
{
    // private static OCRService? _instance;
    //
    // public static OCRService Instance()
    // {
    //     return _instance ??= new OCRService();
    // }
    private readonly PaddleOCREngine? _engine;
    public OCRService()
    {
        OCRModelConfig? config = null;
        var parameter = new OCRParameter();
        _engine = new PaddleOCREngine(config, parameter);
    }
    
    private ApiResponse<string?> ImportImageOCR(string base64ImageString)
    {
        // var fileName = DateTime.Now.ToString("yyyyMMddHHmmss");
        // fileName = GetImage(base64ImageString, fileName);
        var result = "";
        // using (var ocrEngine = new TesseractEngine(@".", "chi_sim", EngineMode.Default))
        // {
        //     using (var img = Pix.LoadFromFile(fileName))
        //     {
        //         using (var page = ocrEngine.Process(img))
        //         {
        //             var text = page.GetText().Replace("\n\n", "");
        //             var start = text.IndexOf('\n');
        //             if (start < 0) return new ApiResponse<string?>(0, "success", result);
        //             text = text.Substring(start).Replace("”", "").Replace("|", "");
        //             while (text.Contains("  "))
        //             {
        //                 text = text.Replace("  ", " ");
        //             }
        //
        //             var lines = text.Split('\n');
        //             var data = new List<dynamic>();
        //             foreach (var line in lines)
        //             {
        //                 if (string.IsNullOrWhiteSpace(line)) continue;
        //                 var items = line.Split(" ");
        //                 try
        //                 {
        //                     data.Add(new
        //                     {
        //                         code = ReplaceChars(items[1]),
        //                         type = ReplaceChars(items[2]),
        //                         x = ReplaceChars(items[3]),
        //                         y = ReplaceChars(items[4]),
        //                         center = ReplaceChars(items[5]),
        //                         w = ReplaceChars(items[2].Split("x")[0]),
        //                         h = ReplaceChars(items[2].Split("x")[1]),
        //                     });
        //                 }
        //                 catch
        //                 {
        //                 }
        //             }
        //
        //             if (data.Count > 0)
        //                 result = JsonSerializer.Serialize(data,
        //                     new JsonSerializerOptions
        //                         { WriteIndented = true, Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) });
        //         }
        //     }
        // }

        return new ApiResponse<string?>(0, "success", result);
    }

    public Task<string> ImportByOCR(string base64ImageString)
    {
        return Task.Run(() =>
        {
            var fileName = DateTime.Now.ToString("yyyyMMddHHmmss");
            fileName = GetImage(base64ImageString, fileName);
            var result = _engine?.DetectText(new Bitmap(fileName));
            if (result == null) return "";
            var resultList = JsonHelper.DeserializeObject<List<OCRResultEntity>>(result.JsonText);
            resultList = resultList.Select((d, index) =>
            {
                d.Index = index;
                return d;
            }).ToList();
            var tempList = resultList.Where(d => !string.IsNullOrEmpty(d.Text) && d.Text.ToUpper().Contains("PT"))
                .ToList();
            var data = new List<dynamic>();
            foreach (var item in tempList)
            {
                try
                {
                    data.Add(new
                    {
                        code = ReplaceChars(resultList[item.Index].Text),
                        type = ReplaceChars(resultList[item.Index + 1].Text),
                        x = ReplaceChars(resultList[item.Index + 2].Text),
                        y = ReplaceChars(resultList[item.Index + 3].Text),
                        center = ReplaceChars(resultList[item.Index + 4].Text),
                        w = ReplaceChars(resultList[item.Index + 1].Text).Split("x")[1],
                        h = ReplaceChars(resultList[item.Index + 1].Text).Split("x")[0],
                        angle = ReplaceChars(resultList[item.Index + 5].Text),
                    });
                }
                catch
                {
                    data.Add(new
                    {
                        code = "",
                        type = "",
                        x = "0",
                        y = "0",
                        center = "0",
                        w = "0",
                        h = "0",
                        angle = "0",
                    });
                }
            }
            
            return data.Count > 0
                ? JsonSerializer.Serialize(data,
                    new JsonSerializerOptions
                        { WriteIndented = true, Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) })
                : "";
        });
    }

    private string ReplaceChars(string? text)
    {
        return string.IsNullOrEmpty(text) ? "" : text.Replace("\u00d7", "x").Replace("_", "").Replace(",", "").Replace(":", "").Replace(";", "").Replace(" ", "").Replace("，", "");
    }
    
    private string GetImage(string base64ImageString, string fileName)
    {
        var imageType = System.Drawing.Imaging.ImageFormat.Gif;
        if (base64ImageString.IndexOf("data:image/jpeg", StringComparison.Ordinal) >= 0)
        {
            imageType = System.Drawing.Imaging.ImageFormat.Jpeg;
            base64ImageString = base64ImageString.Replace("data:image/jpeg;base64,", "");
            fileName += ".jpg";
        }

        if (base64ImageString.IndexOf("data:image/png", StringComparison.Ordinal) >= 0)
        {
            imageType = System.Drawing.Imaging.ImageFormat.Png;
            base64ImageString = base64ImageString.Replace("data:image/png;base64,", "");
            fileName += ".png";
        }

        if (base64ImageString.IndexOf("data:image/bmp", StringComparison.Ordinal) >= 0)
        {
            imageType = System.Drawing.Imaging.ImageFormat.Bmp;
            base64ImageString = base64ImageString.Replace("data:image/bmp;base64,", "");
            fileName += ".bmp";
        }

        if (Equals(imageType, System.Drawing.Imaging.ImageFormat.Gif))
        {
            return "";
        }

        try
        {
            var imageBytes = Convert.FromBase64String(base64ImageString.Replace("data:image/jpeg;base64,", ""));
            using var ms = new MemoryStream(imageBytes);
            var image = System.Drawing.Image.FromStream(ms);
            using (var bmpStream = new MemoryStream())
            {
                image.Save(bmpStream, imageType);
                var bmpBytes = bmpStream.ToArray();
                File.WriteAllBytes(fileName, bmpBytes);
            }

            image.Dispose();
            return fileName;
        }
        catch
        {
            return "";
        }
    }

    public class OCRResultEntity
    {
        public int Index { get; set; }
        public List<BoxPoint>? BoxPoints { get; set; }
        public double Score { get; set; }
        public string? Text { get; set; }
        public int cls_label { get; set; }
        public double cls_score { get; set; }
    }
    public class BoxPoint
    {
        public int X { get; set; }
        public int Y { get; set; }
    }
}