/*
 * 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 Hashtable = require("./../../../unisharp/Hashtable");
const RefOutArgWrapper = require("./../../../unisharp/RefOutArgWrapper");
const StringBuilder = require("./../../../unisharp/StringBuilder");

class CorrPageText {
    
    removeHeadText() {
        if (Utils.isNullOrEmpty(this.headText)) 
            return;
        if (this.m_Top) 
            this.text = this.headText + "\r\n" + (((this.text != null ? this.text : "")));
        else 
            this.text = (((this.text != null ? this.text : ""))) + "\r\n" + this.headText;
    }
    
    toString() {
        return ("N=" + this.number + " '" + ((this.headText != null ? this.headText : "")) + "'");
    }
    
    isNumberDist1(next) {
        if (next.number === 0 || this.number === 0) 
            return false;
        if (next.number === (this.number + 1)) 
            return true;
        if (this.number2 > 0 && next.number === (this.number2 + 1)) 
            return true;
        if (next.number2 > 0 && next.number2 === (this.number + 1)) 
            return true;
        if (next.number2 > 0 && this.number2 > 0 && next.number2 === (this.number2 + 1)) 
            return true;
        return false;
    }
    
    constructor(txt, top) {
        this.number = 0;
        this.number2 = 0;
        this.headText = null;
        this.text = null;
        this.i0 = 0;
        this.i1 = 0;
        this.corr = false;
        this.m_Top = false;
        this.m_Top = top;
        if (txt === null) 
            txt = "";
        let _i0 = 0;
        let _i1 = 0;
        let i = 0;
        if (top) {
            _i0 = 0;
            for (_i1 = _i0; _i1 < txt.length; _i1++) {
                if ((txt.charCodeAt(_i1)) === 0xD || (txt.charCodeAt(_i1)) === 0xA) 
                    break;
            }
            if (_i1 > _i0) {
                this.headText = txt.substring(0, 0 + _i1).trim();
                if (_i1 < txt.length) 
                    this.text = txt.substring(_i1).trim();
                else 
                    this.text = "";
            }
            else 
                this.text = txt;
        }
        else {
            txt = txt.trim();
            _i1 = txt.length - 1;
            for (_i0 = _i1; _i0 >= 0; _i0--) {
                if ((txt.charCodeAt(_i0)) === 0xD || (txt.charCodeAt(_i0)) === 0xA) 
                    break;
            }
            if (_i1 > _i0) {
                if (_i0 < 0) {
                    this.headText = txt;
                    this.text = "";
                }
                else {
                    this.headText = txt.substring(_i0 + 1).trim();
                    this.text = txt.substring(0, 0 + _i0).trim();
                }
            }
            else 
                this.text = txt;
        }
        if (!Utils.isNullOrEmpty(this.headText) && Utils.isDigit(this.headText[0])) {
            for (i = 0; i < this.headText.length; i++) {
                if (!Utils.isDigit(this.headText[i])) 
                    break;
            }
            if (i === this.headText.length || this.headText[i] === ' ') {
                let num = 0;
                let wrapnum337 = new RefOutArgWrapper();
                let inoutres338 = Utils.tryParseInt(this.headText.substring(0, 0 + i), wrapnum337);
                num = wrapnum337.value;
                if (inoutres338) {
                    this.number = num;
                    this.headText = this.headText.substring(i).trim();
                }
            }
        }
        if (!Utils.isNullOrEmpty(this.headText) && Utils.isDigit(this.headText[this.headText.length - 1])) {
            while (true) {
                for (i = this.headText.length - 1; i >= 0; i--) {
                    if (!Utils.isDigit(this.headText[i])) 
                        break;
                }
                if ((i < 0) || this.headText[i] === ' ') {
                    let num = 0;
                    let wrapnum339 = new RefOutArgWrapper();
                    let inoutres340 = Utils.tryParseInt(this.headText.substring(i + 1), wrapnum339);
                    num = wrapnum339.value;
                    if (inoutres340) {
                        if (this.number > 0) 
                            this.number2 = num;
                        else 
                            this.number = num;
                        this.headText = this.headText.substring(0, 0 + i + 1).trim();
                        if (Utils.endsWithString(this.headText, "СТР", true)) 
                            this.headText = this.headText.substring(0, 0 + this.headText.length - 3).trim();
                        if (Utils.endsWithString(this.headText, "СТР.", true)) 
                            this.headText = this.headText.substring(0, 0 + this.headText.length - 4).trim();
                        let from = null;
                        if (Utils.endsWithString(this.headText, "ИЗ", true)) 
                            from = this.headText.substring(0, 0 + this.headText.length - 2).trim();
                        else if (this.headText.endsWith("/") || this.headText.endsWith("\\")) 
                            from = this.headText.substring(0, 0 + this.headText.length - 1).trim();
                        if (from !== null && from.length > 0 && Utils.isDigit(from[from.length - 1])) {
                            this.headText = from;
                            this.number = 0;
                            continue;
                        }
                    }
                }
                break;
            }
        }
        if (top && !Utils.isNullOrEmpty(this.text) && Utils.isDigit(this.text[0])) {
            for (i = 0; i < this.text.length; i++) {
                if (!Utils.isDigit(this.text[i])) 
                    break;
            }
            if (i >= this.text.length || this.text[i] === '\r' || this.text[i] === '\n') {
                let num = 0;
                let wrapnum341 = new RefOutArgWrapper();
                let inoutres342 = Utils.tryParseInt(this.text.substring(0, 0 + i), wrapnum341);
                num = wrapnum341.value;
                if (inoutres342) {
                    this.number = num;
                    if (i >= this.text.length) 
                        this.text = "";
                    else 
                        this.text = this.text.substring(i).trim();
                }
            }
        }
        if (!top && !Utils.isNullOrEmpty(this.text) && Utils.isDigit(this.text[this.text.length - 1])) {
            for (i = this.text.length - 1; i >= 0; i--) {
                if (!Utils.isDigit(this.text[i])) 
                    break;
            }
            if ((i < 0) || this.text[i] === '\r' || this.text[i] === '\n') {
                let num = 0;
                let wrapnum343 = new RefOutArgWrapper();
                let inoutres344 = Utils.tryParseInt(this.text.substring(i + 1), wrapnum343);
                num = wrapnum343.value;
                if (inoutres344) {
                    this.number = num;
                    if (i <= 0) 
                        this.text = "";
                    else 
                        this.text = this.text.substring(0, 0 + i).trim();
                }
            }
        }
        if (Utils.isNullOrEmpty(this.headText)) 
            this.headText = null;
    }
    
    static process(pts) {
        let cou = 0;
        let i = 0;
        for (const p of pts) {
            p.corr = false;
        }
        let res = new StringBuilder();
        for (i = 1; i < (pts.length - 1); i++) {
            if (pts[i - 1].number > 0 && ((pts[i].number === 0 || pts[i].number !== (pts[i - 1].number + 1)))) {
                let j = 0;
                let ok1 = false;
                let ok2 = false;
                let err = 0;
                for (j = i + 1; j < pts.length; j++) {
                    if (pts[j].number > 0) {
                        if (pts[j].number === (pts[i - 1].number + (((j - i) + 1)))) {
                            ok1 = true;
                            break;
                        }
                        if (((j + 2) < pts.length) && pts[j + 1].number === (pts[j].number + 1) && pts[j + 2].number === (pts[j].number + 2)) {
                            ok2 = true;
                            break;
                        }
                        if ((++err) > 10) 
                            break;
                    }
                }
                if (ok1 || ok2) {
                    for (let k = i; k < j; k++) {
                        pts[k].number = 0;
                    }
                }
            }
        }
        let noCorrFirst = false;
        if (pts.length > 0 && pts[0].number > 1900) {
            pts[0].number = 0;
            noCorrFirst = true;
        }
        if (pts.length > 2) {
            if (pts[0].number !== 1 && pts[1].number > 0 && pts[2].number === (pts[1].number + 1)) {
                if (pts[0].number !== (pts[1].number - 1)) {
                    pts[0].number = pts[1].number - 1;
                    noCorrFirst = true;
                }
            }
        }
        let firstPage = 0;
        if (pts.length > 4 && pts[0].number === 0) {
            for (i = 0; i < (pts.length - 5); i++) {
                if (pts[i].number !== 0) {
                    let ok1 = true;
                    for (let j = i + 1; (j < pts.length) && (j < (i + 4)); j++) {
                        if (!pts[j].isNumberDist1(pts[j + 1])) {
                            ok1 = false;
                            break;
                        }
                    }
                    if (ok1) {
                        firstPage = i;
                        for (--i; i >= 0; i--) {
                            pts[i].number = pts[i + 1].number - 1;
                        }
                    }
                    break;
                }
            }
        }
        let errcou = 0;
        for (i = 0; i < (pts.length - 1); i++) {
            if (pts[i + 1].number <= 0) {
                if ((i + 1) < pts.length) 
                    continue;
                errcou++;
                continue;
            }
            if (pts[i].number <= 0) {
                if (i <= firstPage) 
                    continue;
                errcou++;
                continue;
            }
            if (pts[i].isNumberDist1(pts[i + 1])) 
                cou++;
            else if (i === 0) {
            }
            else 
                errcou++;
        }
        let ok = false;
        if (cou === 0) {
            if ((pts.length === 3 && pts[1].number === 2 && pts[0].number === 0) && pts[2].number === 0) 
                ok = true;
            else if (pts.length === 2 && pts[1].number === 2 && ((pts[0].number === 1 || pts[0].number === 0))) 
                ok = true;
            else 
                ok = false;
        }
        else if (errcou === 0) 
            ok = true;
        let colstat = new Hashtable();
        for (i = 1; i < pts.length; i++) {
            if (pts[i].headText !== null) {
                if (colstat.containsKey(pts[i].headText)) 
                    colstat.put(pts[i].headText, colstat.get(pts[i].headText) + 1);
                else 
                    colstat.put(pts[i].headText, 1);
            }
        }
        let lev = Utils.intDiv(pts.length, 2);
        if (lev < 2) 
            lev = 2;
        for (i = 1; i < pts.length; i++) {
            let h = pts[i].headText;
            if (h === null) 
                continue;
            let c = colstat.get(h);
            if (c >= lev) 
                pts[i].corr = true;
            else 
                pts[i].removeHeadText();
        }
        for (const kp of colstat.entries) {
            if (kp.value >= lev && kp.key.length > 5) {
                if (res.length > 0) 
                    res.append("\r\n");
                res.append(kp.key);
            }
        }
        if (cou > (errcou * 3)) {
            for (const p of pts) {
                if (p.number > 0) {
                    if (noCorrFirst && p === pts[0]) 
                        continue;
                    if (!p.corr) 
                        p.removeHeadText();
                    p.corr = true;
                }
            }
        }
        return (res.length === 0 ? null : res.toString());
    }
    
    static _new357(_arg1, _arg2, _arg3, _arg4) {
        let res = new CorrPageText(_arg1, _arg2);
        res.i0 = _arg3;
        res.i1 = _arg4;
        return res;
    }
}


module.exports = CorrPageText