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.RegularExpressions;
using System.Text.Unicode;
using System.Threading.Tasks;
using detect.gui.Models;
using PaddleOCRSharp;

namespace detect.gui.Services;

public class OCRService
{
    private readonly PaddleOCREngine? _engine;
    public OCRService()
    {
        OCRModelConfig? config = null;
        var parameter = new OCRParameter();
        _engine = new PaddleOCREngine(config, parameter);
    }

    public Task<string> ImportByOCR(string base64ImageString)
    {
        return Task.Run(() =>
        {
            var image = GetImage(base64ImageString);
            if (image is null) return "";
            var result = _engine?.DetectText(image);
            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) &&
                                                 (Enumerable.Range('A', 'Z' - 'A' + 1)
                                                     .Select(i => "P" + (char)i)
                                                     .Any(substring => d.Text.ToUpper().Contains(substring)) ||
                                                  d.Text.ToUpper().Contains("VB")))
                .ToList();
            var data = new List<dynamic>();
            foreach (var item in tempList)
            {
                try
                {
                    var w = "0";
                    var h = "0";
                    var type = ReplaceChars(resultList[item.Index + 1].Text);
                    if (string.IsNullOrWhiteSpace(type)) continue;
                    type = Regex.Replace(type, "[A-Z]", string.Empty);
                    if (type.Contains('-', StringComparison.CurrentCultureIgnoreCase))
                    {
                        type = type.Split("-")[0];
                        if (type.Contains('x', StringComparison.CurrentCultureIgnoreCase))
                        {
                            w = type.Split("x")[0];
                            h = type.Split("x")[1];
                        }
                        else
                        {
                            w = type;
                            h = type;
                        }
                    }
                    else if (type.Contains('x', StringComparison.CurrentCultureIgnoreCase))
                    {
                        w = type.Split("x")[0];
                        h = type.Split("x")[1];
                    }
                    else
                        continue;
                    data.Add(new
                    {
                        sn = ReplaceChars(resultList[item.Index - 1].Text),
                        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 = w,
                        h = h,
                        angle = ReplaceChars(resultList[item.Index + 5].Text),
                    });
                }
                catch {}  // 出错则忽略
            }

            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 Image? GetImage(string base64ImageString)
    {
        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 null;
        }

        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);
            return image;
        }
        catch
        {
            return null;
        }
    }

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