/*
 * 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
 */

const Utils = require("./../unisharp/Utils");
const XmlDocument = require("./../unisharp/XmlDocument");
const WebClient = require("./../unisharp/WebClient");

const UnilayPage = require("./../unitext/UnilayPage");

/**
 * Поддержка OCR (запросы к внешнему серверу OCR.Server.exe)
 */
class OCRService {
    
    /**
     * Запрос к серверу, жив ли он
     * @return null, если недоступен, иначе строка "C" (при поддержке CuneiForm) и + "M" (при поддержке Modi)
     */
    static checkServer() {
        if (OCRService.URI === null) 
            throw new Error("Uri not defined");
        OCRService._corrUri();
        try {
            let web = new WebClient();
            let dat = web.downloadData(OCRService.URI);
            if (dat !== null) 
                return Utils.decodeString("UTF-8", dat, 0, -1);
        } catch (ex) {
        }
        return null;
    }
    
    static _corrUri() {
        if (OCRService.URI === null) 
            return;
        if (!OCRService.URI.startsWith("http")) 
            OCRService.URI = "http://" + OCRService.URI;
        if (!OCRService.URI.endsWith("/")) 
            OCRService.URI += "/";
    }
    
    /**
     * Проверить, что страница нуждается в распознавании (содержит картинку и не содержит текста)
     * @param page страница с картинкой в page.ImageContent)
     * @return при true страница нуждается в распознавании
     */
    static checkPageNeedOCR(page) {
        if (page === null) 
            return false;
        if (page.imageContent === null || (page.imageContent.length < 10)) 
            return false;
        if (page.rects.length === 0) 
            return true;
        let chars = 0;
        let digs = 0;
        let punkts = 0;
        for (const r of page.rects) {
            if (r.text !== null) {
                for (const ch of r.text) {
                    if (Utils.isLetter(ch)) 
                        chars++;
                    else if (Utils.isDigit(ch)) 
                        digs++;
                    else if (!Utils.isWhitespace(ch)) 
                        punkts++;
                }
            }
        }
        if (punkts > chars) 
            return true;
        if (chars < 20) 
            return true;
        return false;
    }
    
    /**
     * Распознать текст с картинки страницы
     * @param page страница с картинкой в page.ImageContent)
     * @param rotate нужно ли вращать (по умолчанию, нет)
     * @param quick при true быстрый способ, но ниже качество (не задействуется второй движок)
     * @return при true результат запишется в page.Rects
     */
    static process(page, rotate = false, quick = false) {
        if (OCRService.URI === null) 
            throw new Error("Uni not defined");
        if (page === null || page.imageContent === null || (page.imageContent.length < 10)) 
            throw new Error("Page image not defined");
        OCRService._corrUri();
        let web = new WebClient();
        let dat = web.uploadData((OCRService.URI + "?oper=start&rotate=" + (rotate ? "true" : "false") + "&quick=" + (quick ? "true" : "false")), page.imageContent);
        if (dat === null) 
            return false;
        let str = Utils.decodeString("UTF-8", dat, 0, -1);
        if (Utils.startsWithString(str, "ERROR:", true)) 
            throw new Error(str.substring(6).trim());
        let id = str;
        while (true) {
            dat = web.downloadData((OCRService.URI + "?oper=status&task=" + id));
            str = Utils.decodeString("UTF-8", dat, 0, -1);
            if (Utils.startsWithString(str, "ERROR:", true)) 
                throw new Error(str.substring(6).trim());
            if (str === "completed") 
                break;
        }
        dat = web.downloadData((OCRService.URI + "?oper=result&task=" + id));
        str = Utils.decodeString("UTF-8", dat, 0, -1);
        if (Utils.startsWithString(str, "ERROR:", true)) {
            str = str.substring(6).trim();
            if (Utils.startsWithString(str, "no recognized text", true)) 
                return false;
            throw new Error(str.substring(6).trim());
        }
        let xml = new XmlDocument();
        xml.loadXml(str);
        let page0 = new UnilayPage();
        page0.restore(xml.document_element);
        if (page0.rects.length === 0) 
            return false;
        page.rects = page0.rects;
        return true;
    }
    
    static static_constructor() {
        OCRService.URI = null;
    }
}


OCRService.static_constructor();

module.exports = OCRService