/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter UniSharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

using System;
using System.Net;
using System.Text;
using System.Threading;
using System.Xml;

namespace Pullenti.Util
{
    /// <summary>
    /// Поддержка OCR (запросы к внешнему серверу OCR.Server.exe)
    /// </summary>
    public static class OCRService
    {
        /// <summary>
        /// Адрес сервера (необходимо устанавливать сначала)
        /// </summary>
        public static string Uri;
        /// <summary>
        /// Запрос к серверу, жив ли он
        /// </summary>
        /// <return>null, если недоступен, иначе строка "C" (при поддержке CuneiForm) и + "M" (при поддержке Modi)</return>
        public static string CheckServer()
        {
            if (Uri == null) 
                throw new Exception("Uri not defined");
            _corrUri();
            try 
            {
                WebClient web = new WebClient();
                byte[] dat = web.DownloadData(Uri);
                if (dat != null) 
                    return Encoding.UTF8.GetString(dat);
            }
            catch(Exception ex) 
            {
            }
            return null;
        }
        static void _corrUri()
        {
            if (Uri == null) 
                return;
            if (!Uri.StartsWith("http")) 
                Uri = "http://" + Uri;
            if (!Uri.EndsWith("/")) 
                Uri += "/";
        }
        /// <summary>
        /// Проверить, что страница нуждается в распознавании (содержит картинку и не содержит текста)
        /// </summary>
        /// <param name="page">страница с картинкой в page.ImageContent)</param>
        /// <return>при true страница нуждается в распознавании</return>
        public static bool CheckPageNeedOCR(Pullenti.Unitext.UnilayPage page)
        {
            if (page == null) 
                return false;
            if (page.ImageContent == null || (page.ImageContent.Length < 10)) 
                return false;
            if (page.Rects.Count == 0) 
                return true;
            int chars = 0;
            int digs = 0;
            int punkts = 0;
            foreach (Pullenti.Unitext.UnilayRectangle r in page.Rects) 
            {
                if (r.Text != null) 
                {
                    foreach (char ch in r.Text) 
                    {
                        if (char.IsLetter(ch)) 
                            chars++;
                        else if (char.IsDigit(ch)) 
                            digs++;
                        else if (!char.IsWhiteSpace(ch)) 
                            punkts++;
                    }
                }
            }
            if (punkts > chars) 
                return true;
            if (chars < 20) 
                return true;
            return false;
        }
        /// <summary>
        /// Распознать текст с картинки страницы
        /// </summary>
        /// <param name="page">страница с картинкой в page.ImageContent)</param>
        /// <param name="rotate">нужно ли вращать (по умолчанию, нет)</param>
        /// <param name="quick">при true быстрый способ, но ниже качество (не задействуется второй движок)</param>
        /// <return>при true результат запишется в page.Rects</return>
        public static bool Process(Pullenti.Unitext.UnilayPage page, bool rotate = false, bool quick = false)
        {
            if (Uri == null) 
                throw new Exception("Uni not defined");
            if (page == null || page.ImageContent == null || (page.ImageContent.Length < 10)) 
                throw new Exception("Page image not defined");
            _corrUri();
            WebClient web = new WebClient();
            byte[] dat = web.UploadData(string.Format("{0}?oper=start&rotate={1}&quick={2}", Uri, (rotate ? "true" : "false"), (quick ? "true" : "false")), page.ImageContent);
            if (dat == null) 
                return false;
            string str = Encoding.UTF8.GetString(dat);
            if (str.StartsWith("ERROR:", StringComparison.OrdinalIgnoreCase)) 
                throw new Exception(str.Substring(6).Trim());
            string id = str;
            while (true) 
            {
                Thread.Sleep(1000);
                dat = web.DownloadData(string.Format("{0}?oper=status&task={1}", Uri, id));
                str = Encoding.UTF8.GetString(dat);
                if (str.StartsWith("ERROR:", StringComparison.OrdinalIgnoreCase)) 
                    throw new Exception(str.Substring(6).Trim());
                if (str == "completed") 
                    break;
            }
            dat = web.DownloadData(string.Format("{0}?oper=result&task={1}", Uri, id));
            str = Encoding.UTF8.GetString(dat);
            if (str.StartsWith("ERROR:", StringComparison.OrdinalIgnoreCase)) 
            {
                str = str.Substring(6).Trim();
                if (str.StartsWith("no recognized text", StringComparison.OrdinalIgnoreCase)) 
                    return false;
                throw new Exception(str.Substring(6).Trim());
            }
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(str);
            Pullenti.Unitext.UnilayPage page0 = new Pullenti.Unitext.UnilayPage();
            page0.Restore(xml.DocumentElement);
            if (page0.Rects.Count == 0) 
                return false;
            page.Rects = page0.Rects;
            return true;
        }
    }
}