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

const UnitextItem = require("./../../UnitextItem");
const CreateDocumentParam = require("./../../CreateDocumentParam");
const CorrLine = require("./CorrLine");
const CorrTable = require("./CorrTable");
const UnitextTable = require("./../../UnitextTable");
const CorrFootnoteTyps = require("./CorrFootnoteTyps");
const CorrFootnoteContainer = require("./CorrFootnoteContainer");
const UnitextCorrPdfPage = require("./UnitextCorrPdfPage");
const UnitextContainerType = require("./../../UnitextContainerType");
const LocCorrTyp = require("./LocCorrTyp");
const UnitextPlaintext = require("./../../UnitextPlaintext");
const UnitextContainer = require("./../../UnitextContainer");
const UnitextPagebreak = require("./../../UnitextPagebreak");
const UnitextHyperlink = require("./../../UnitextHyperlink");
const UnitextNewline = require("./../../UnitextNewline");
const FileFormat = require("./../../FileFormat");
const GetPlaintextParam = require("./../../GetPlaintextParam");
const CorrPageText = require("./CorrPageText");

class UnitextCorrHelper {
    
    static removePageBreakNumeration(doc) {
        let cnt = Utils.as(doc.content, UnitextContainer);
        if (cnt === null) 
            return;
        let tmp = new StringBuilder();
        let tmpCnt = new UnitextContainer();
        let corr = false;
        for (let k = 0; k < 2; k++) {
            let pages = new Array();
            for (let i = 0; i < cnt.children.length; i++) {
                let i0 = 0;
                let i1 = 0;
                tmpCnt.children.splice(0, tmpCnt.children.length);
                if (k === 0) {
                    if (i === 0) {
                    }
                    else if ((cnt.children[i - 1] instanceof UnitextPagebreak) && (cnt.children[i] instanceof UnitextPlaintext)) {
                    }
                    else 
                        continue;
                    i0 = i;
                    for (i1 = i0; i1 < cnt.children.length; i1++) {
                        let chh = cnt.children[i1];
                        if (chh instanceof UnitextPlaintext) {
                        }
                        else if (chh instanceof UnitextHyperlink) {
                        }
                        else 
                            break;
                        tmpCnt.children.push(chh);
                    }
                    i1--;
                }
                else {
                    if (i === (cnt.children.length - 1)) 
                        i1 = i;
                    else if (cnt.children[i] instanceof UnitextPagebreak) 
                        i1 = i - 1;
                    else 
                        continue;
                    for (i0 = i1; i0 >= 0; i0--) {
                        let chh = cnt.children[i0];
                        if (chh instanceof UnitextPlaintext) {
                        }
                        else if (chh instanceof UnitextHyperlink) {
                        }
                        else 
                            break;
                        tmpCnt.children.push(chh);
                    }
                    i0++;
                }
                if (tmpCnt.children.length === 0) 
                    continue;
                tmp.length = 0;
                tmpCnt.getPlaintext(tmp, GetPlaintextParam._new356(false));
                if (tmp.length === 0) 
                    continue;
                let page = CorrPageText._new357(tmp.toString(), k === 0, i0, i1);
                pages.push(page);
            }
            if (pages.length < 2) 
                continue;
            let tittext = CorrPageText.process(pages);
            let k1 = k;
            for (let i = pages.length - 1; i >= 0; i--) {
                if (pages[i].corr) {
                    if (i === 0) {
                    }
                    for (let j = pages[i].i0; j <= pages[i].i1; j++) {
                        let pl = Utils.as(cnt.children[j], UnitextPlaintext);
                        if (pl !== null && pl.layout !== null) {
                            for (let jj = 0; jj < pl.layout.length; jj++) {
                                if (pl.layout[jj] !== null) 
                                    pl.layout[jj].ignored = true;
                            }
                        }
                    }
                    cnt.children.splice(pages[i].i0, (pages[i].i1 + 1) - pages[i].i0);
                    corr = true;
                    k1 = k - 1;
                }
            }
            if (tittext !== null) {
            }
            k = k1;
        }
        for (let i = cnt.children.length - 1; i >= 0; i--) {
            if (i >= cnt.children.length) 
                continue;
            let pt = Utils.as(cnt.children[i], UnitextPlaintext);
            if (pt === null) 
                continue;
            let n = 0;
            let wrapn358 = new RefOutArgWrapper();
            let inoutres359 = Utils.tryParseInt(pt.text.trim(), wrapn358);
            n = wrapn358.value;
            if (!inoutres359) 
                continue;
            if (n > 3000) 
                continue;
            if (i === 0 || (cnt.children[i - 1] instanceof UnitextPagebreak) || ((i > 1 && (cnt.children[i - 1] instanceof UnitextNewline) && (cnt.children[i - 2] instanceof UnitextPagebreak)))) {
                if (((i + 1) < cnt.children.length) && (cnt.children[i + 1] instanceof UnitextNewline)) {
                    if (pt.layout !== null) {
                        for (const la of pt.layout) {
                            if (la !== null) {
                                la.ignored = true;
                                la.page.topNumber = n;
                            }
                        }
                    }
                    cnt.children.splice(i, 2);
                    continue;
                }
            }
            else if ((i + 1) === cnt.children.length || (cnt.children[i + 1] instanceof UnitextPagebreak) || ((((i + 2) < cnt.children.length) && (cnt.children[i + 1] instanceof UnitextNewline) && (cnt.children[i + 2] instanceof UnitextPagebreak)))) {
                if (i > 0 && (cnt.children[i - 1] instanceof UnitextNewline)) {
                    if (pt.layout !== null) {
                        for (const la of pt.layout) {
                            if (la !== null) {
                                la.ignored = true;
                                la.page.bottomNumber = n;
                            }
                        }
                    }
                    cnt.children.splice(i - 1, 2);
                    continue;
                }
            }
        }
        if (corr) 
            doc.optimize(false, null);
    }
    
    static removeFalseNewLines(doc, replaceNbsp, pars) {
        if (doc === null || doc.content === null) 
            return;
        let cnt = Utils.as(doc.content, UnitextContainer);
        if (cnt === null) 
            return;
        let cr1 = 0;
        let cr2 = 0;
        let crA = 0;
        for (const v of cnt.children) {
            if (v instanceof UnitextNewline) {
                let co = v.count;
                if (co === 1) 
                    cr1++;
                else if (co === 2) 
                    cr2++;
                else 
                    crA++;
            }
        }
        if (cr2 > (((cr1 + crA)) * 3) && cr2 > 2) {
            if (doc.sourceFormat === FileFormat.DOC || doc.sourceFormat === FileFormat.DOCX || doc.sourceFormat === FileFormat.DOCXML) {
            }
            else 
                cnt.correct(LocCorrTyp.MERGENEWLINES, null);
        }
        let lines = CorrLine.parseList(cnt);
        let cou = 0;
        let len = 0;
        let nbspCount = 0;
        let spCount = 0;
        for (const l of lines) {
            if (l.isPureText) {
                for (const ch of l.text) {
                    if (ch === ' ') 
                        spCount++;
                    else if (ch === (String.fromCharCode(0xA0))) 
                        nbspCount++;
                }
            }
            if ((l.isPureText && l.newLines === 1) || l.pageBreakAfter) {
                cou++;
                len += l.length;
            }
        }
        if (replaceNbsp && nbspCount > 100 && nbspCount > (spCount * 2)) {
            doc.content.correct(LocCorrTyp.NPSP2SP, null);
            for (const s of doc.sections) {
                for (const it of s.items) {
                    if (it.content !== null) 
                        it.content.correct(LocCorrTyp.NPSP2SP, null);
                }
            }
        }
        if (cou === 0) 
            return;
        len = Utils.intDiv(len, cou);
        if (cou < 3) 
            return;
        if ((len < UnitextCorrHelper.minLineLen) || len > UnitextCorrHelper.maxLineLen) 
            return;
        let minLen = Math.floor((0.80 * (len)));
        let maxLen = Math.floor((1.20 * (len)));
        for (let i = 0; i < (lines.length - 1); i++) {
            let l1 = lines[i];
            let l2 = lines[i + 1];
            if (!l1.isPureText || !l2.isPureText) 
                continue;
            if (l1.length < minLen) 
                continue;
            if (l1.canFollowed(l2)) 
                l2.merge = true;
        }
        let changed = false;
        for (let i = lines.length - 1; i > 0; i--) {
            if (lines[i].merge) {
                if (lines[i - 1].pageBreakAfter) 
                    continue;
                let i0 = lines[i - 1].lastInd + 1;
                let i1 = lines[i].firstInd - 1;
                if (i0 <= i1) {
                    changed = true;
                    if (i0 < i1) 
                        cnt.children.splice(i0 + 1, i1 - i0);
                    cnt.children[i0] = UnitextPlaintext._new57(" ");
                }
            }
        }
        if (changed) {
            if (pars !== null) 
                doc.optimize(false, CreateDocumentParam._new361(pars));
            else 
                doc.optimize(false, null);
        }
    }
    
    static restoreTextFootnotes(doc) {
        if (doc === null || doc.content === null) 
            return;
        if (doc.content instanceof UnitextTable) {
            UnitextCorrHelper.restoreTextFootnotesInTable(Utils.as(doc.content, UnitextTable));
            return;
        }
        let cnt = Utils.as(doc.content, UnitextContainer);
        if (cnt === null) 
            return;
        if (doc.sourceFormat === FileFormat.PDF || doc.sourceFormat === FileFormat.DJVU) {
            UnitextCorrPdfPage.correct(cnt);
            return;
        }
        let fcl = new Array();
        let numStart = 1;
        for (let i = 0; i < cnt.children.length; i++) {
            if (i === 149) {
            }
            if (cnt.children[i] instanceof UnitextTable) {
                UnitextCorrHelper.restoreTextFootnotesInTable(Utils.as(cnt.children[i], UnitextTable));
                continue;
            }
            let fc = CorrFootnoteContainer.tryParse(cnt.children, i, numStart);
            if (fc === null) 
                continue;
            fcl.push(fc);
            if (fcl.length === 19) {
            }
            i = fc.endInd;
            if (fc.typ === CorrFootnoteTyps.DIGIT || fc.typ === CorrFootnoteTyps.SUPDIGIT) 
                numStart = fc.startNumber + fc.items.length;
            else 
                numStart += fc.items.length;
        }
        if (fcl.length === 0) 
            return;
        let isChanged = false;
        for (let i = fcl.length - 1; i >= 0; i--) {
            let ind0 = 0;
            let ind1 = fcl[i].beginInd - 1;
            if (i > 0) 
                ind0 = fcl[i - 1].endInd + 1;
            if (i === 8) {
            }
            let corr = false;
            for (let k = 0; k < 2; k++) {
                for (let j = ind0; j <= ind1; j++) {
                    if (j === 40) {
                    }
                    let it = fcl[i].correctItem(cnt.children[j], k === 1);
                    if (it !== null) {
                        cnt.children[j] = it;
                        corr = true;
                    }
                }
                if (corr || fcl[i].typ !== CorrFootnoteTyps.STARS) 
                    break;
            }
            if (corr) {
                isChanged = true;
                cnt.children.splice(fcl[i].beginInd, (fcl[i].endInd + 1) - fcl[i].beginInd);
                if (((fcl[i].beginInd < cnt.children.length) && (cnt.children[fcl[i].beginInd] instanceof UnitextNewline) && fcl[i].beginInd > 0) && (cnt.children[fcl[i].beginInd - 1] instanceof UnitextNewline)) 
                    cnt.children.splice(fcl[i].beginInd, 1);
            }
        }
        if (isChanged) 
            doc.optimize(false, null);
    }
    
    static restoreTextFootnotesInTable(tab) {
        let isChanged = false;
        for (let r = 0; r < tab.rowsCount; r++) {
            for (let c = 0; c < tab.colsCount; c++) {
                let cel = tab.getCell(r, c);
                if (cel === null) 
                    continue;
                if (cel.colBegin !== c || cel.rowBegin !== r) 
                    continue;
                if (cel.content === null) 
                    continue;
                let fn = CorrFootnoteContainer.tryParse1(cel.content);
                if (fn === null) 
                    continue;
                for (let cc = cel.colBegin; cc <= cel.colEnd; cc++) {
                    let cel0 = tab.getCell(r - 1, cc);
                    if (cel0 === null) 
                        continue;
                    if (cel0.content === null) 
                        continue;
                    let re = fn.correctItem(cel0.content, false);
                    if (re === null) 
                        continue;
                    cel0.content = re;
                    cel.content = null;
                    isChanged = true;
                }
            }
        }
        if (isChanged) 
            tab.optimize(false, null);
    }
    
    static restoreTables(doc) {
        let cnt = Utils.as(doc.content, UnitextContainer);
        if (cnt !== null) 
            return UnitextCorrHelper._restoreTables(cnt);
        return false;
    }
    
    static _restoreTables(cnt) {
        if (cnt === null) 
            return false;
        let ret = false;
        for (const ch of cnt.children) {
            if (ch instanceof UnitextContainer) {
                if (UnitextCorrHelper._restoreTables(Utils.as(ch, UnitextContainer))) 
                    ret = true;
            }
        }
        let lines = CorrLine.parseList(cnt);
        let tabs = new Array();
        for (let i = 0; i < lines.length; i++) {
            let ii = 0;
            let wrapii362 = new RefOutArgWrapper();
            let tab = CorrTable.tryParse(lines, i, wrapii362);
            ii = wrapii362.value;
            if (tab !== null) {
                tabs.push(tab);
                i = tab.endInd;
            }
            else 
                i = ii;
        }
        if (tabs.length === 0) 
            return ret;
        for (let i = tabs.length - 1; i >= 0; i--) {
            let i0 = lines[tabs[i].beginInd].firstInd;
            let i1 = lines[tabs[i].endInd].lastInd;
            if (i0 < i1) {
                cnt.children.splice(i0 + 1, i1 - i0);
                cnt.children[i0] = tabs[i].result;
            }
        }
        if (cnt.typ === UnitextContainerType.MONOSPACE) 
            cnt.typ = UnitextContainerType.UNDEFINED;
        return true;
    }
    
    static corrNbsp(text) {
        if (text.indexOf(String.fromCharCode(0xA0)) < 0) 
            return text;
        return Utils.replaceString(text, String.fromCharCode(0xA0), ' ');
    }
    
    static static_constructor() {
        UnitextCorrHelper.minLineLen = 50;
        UnitextCorrHelper.maxLineLen = 100;
    }
}


UnitextCorrHelper.static_constructor();

module.exports = UnitextCorrHelper