# 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

import xml.etree
from pullenti.unisharp.Utils import Utils
from pullenti.unisharp.Misc import WebClient

from pullenti.unitext.UnilayPage import UnilayPage

class OCRService:
    """ Поддержка OCR (запросы к внешнему серверу OCR.Server.exe) """
    
    URI = None
    """ Адрес сервера (необходимо устанавливать сначала) """
    
    @staticmethod
    def check_server() -> str:
        """ Запрос к серверу, жив ли он
        
        Returns:
            str: null, если недоступен, иначе строка "C" (при поддержке CuneiForm) и + "M" (при поддержке Modi)
        """
        if (OCRService.URI is None): 
            raise Utils.newException("Uri not defined", None)
        OCRService.__corr_uri()
        try: 
            web = WebClient()
            dat = web.download_data(OCRService.URI)
            if (dat is not None): 
                return dat.decode("UTF-8", 'ignore')
        except Exception as ex: 
            pass
        return None
    
    @staticmethod
    def __corr_uri() -> None:
        if (OCRService.URI is None): 
            return
        if (not OCRService.URI.startswith("http")): 
            OCRService.URI = ("http://" + OCRService.URI)
        if (not OCRService.URI.endswith("/")): 
            OCRService.URI += "/"
    
    @staticmethod
    def check_page_needocr(page : 'UnilayPage') -> bool:
        """ Проверить, что страница нуждается в распознавании (содержит картинку и не содержит текста)
        
        Args:
            page(UnilayPage): страница с картинкой в page.ImageContent)
        
        Returns:
            bool: при true страница нуждается в распознавании
        """
        if (page is None): 
            return False
        if (page.image_content is None or (len(page.image_content) < 10)): 
            return False
        if (len(page.rects) == 0): 
            return True
        chars = 0
        digs = 0
        punkts = 0
        for r in page.rects: 
            if (r.text is not None): 
                for ch in r.text: 
                    if (str.isalpha(ch)): 
                        chars += 1
                    elif (str.isdigit(ch)): 
                        digs += 1
                    elif (not Utils.isWhitespace(ch)): 
                        punkts += 1
        if (punkts > chars): 
            return True
        if (chars < 20): 
            return True
        return False
    
    @staticmethod
    def process(page : 'UnilayPage', rotate : bool=False, quick : bool=False) -> bool:
        """ Распознать текст с картинки страницы
        
        Args:
            page(UnilayPage): страница с картинкой в page.ImageContent)
            rotate(bool): нужно ли вращать (по умолчанию, нет)
            quick(bool): при true быстрый способ, но ниже качество (не задействуется второй движок)
        
        Returns:
            bool: при true результат запишется в page.Rects
        """
        if (OCRService.URI is None): 
            raise Utils.newException("Uni not defined", None)
        if (page is None or page.image_content is None or (len(page.image_content) < 10)): 
            raise Utils.newException("Page image not defined", None)
        OCRService.__corr_uri()
        web = WebClient()
        dat = web.upload_data("{0}?oper=start&rotate={1}&quick={2}".format(OCRService.URI, ("true" if rotate else "false"), ("true" if quick else "false")), page.image_content)
        if (dat is None): 
            return False
        str0_ = dat.decode("UTF-8", 'ignore')
        if (Utils.startsWithString(str0_, "ERROR:", True)): 
            raise Utils.newException(str0_[6:].strip(), None)
        id0_ = str0_
        while True:
            dat = web.download_data("{0}?oper=status&task={1}".format(OCRService.URI, id0_))
            str0_ = dat.decode("UTF-8", 'ignore')
            if (Utils.startsWithString(str0_, "ERROR:", True)): 
                raise Utils.newException(str0_[6:].strip(), None)
            if (str0_ == "completed"): 
                break
        dat = web.download_data("{0}?oper=result&task={1}".format(OCRService.URI, id0_))
        str0_ = dat.decode("UTF-8", 'ignore')
        if (Utils.startsWithString(str0_, "ERROR:", True)): 
            str0_ = str0_[6:].strip()
            if (Utils.startsWithString(str0_, "no recognized text", True)): 
                return False
            raise Utils.newException(str0_[6:].strip(), None)
        xml0_ = None # new XmlDocument
        xml0_ = Utils.parseXmlFromString(str0_)
        page0 = UnilayPage()
        page0.restore(xml0_.getroot())
        if (len(page0.rects) == 0): 
            return False
        page.rects = page0.rects
        return True