/*
 * 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 MiscHelper = require("./../util/MiscHelper");
const UnitextStyledFragmentType = require("./UnitextStyledFragmentType");
const LocCorrTyp = require("./internal/uni/LocCorrTyp");
const UnitextItem = require("./UnitextItem");
const UnitextPlaintextType = require("./UnitextPlaintextType");
const UnitextDocument = require("./UnitextDocument");

/**
 * Фрагмент плоского текста.
 * 
 */
class UnitextPlaintext extends UnitextItem {
    
    constructor() {
        super();
        this.text = null;
        this.typ = UnitextPlaintextType.SIMPLE;
        this.layout = null;
    }
    
    clone() {
        let res = new UnitextPlaintext();
        res._cloneFrom(this);
        res.text = this.text;
        res.typ = this.typ;
        res.layout = this.layout;
        return res;
    }
    
    get isWhitespaces() {
        if (this.text === null) 
            return true;
        for (const ch of this.text) {
            if (!Utils.isWhitespace(ch)) 
                return false;
        }
        return true;
    }
    
    get innerTag() {
        return "txt";
    }
    
    mergeWith(pt) {
        if (pt.text === null || this.text === null) 
            return;
        if (pt.layout !== null || this.layout !== null) {
            let lay = Array(pt.text.length + this.text.length).fill(null);
            if (this.layout !== null) {
                for (let i = 0; i < this.layout.length; i++) {
                    if (i < lay.length) 
                        lay[i] = this.layout[i];
                }
            }
            if (pt.layout !== null) {
                for (let i = 0; i < pt.layout.length; i++) {
                    if ((this.text.length + i) < lay.length) 
                        lay[this.text.length + i] = pt.layout[i];
                }
            }
            this.layout = lay;
        }
        if (this.isWhitespaces && !pt.isWhitespaces) 
            this.m_StyledFrag = pt.m_StyledFrag;
        else if (!this.isWhitespaces && pt.isWhitespaces) {
        }
        else if (this.m_StyledFrag === null) 
            this.m_StyledFrag = pt.m_StyledFrag;
        else if (pt.m_StyledFrag !== null && this.m_StyledFrag.toString() !== pt.m_StyledFrag.toString()) {
            if (this.m_StyledFrag.parent !== null && pt.m_StyledFrag.parent === this.m_StyledFrag.parent) {
                Utils.removeItem(this.m_StyledFrag.parent.children, pt.m_StyledFrag);
                pt.m_StyledFrag.parent = this.m_StyledFrag;
                this.m_StyledFrag.children.push(pt.m_StyledFrag);
                pt.m_StyledFrag.dispInline = this.text.length;
                pt.m_StyledFrag.lenInline = pt.text.length;
            }
        }
        this.text += pt.text;
        if (pt.id !== null && this.id === null) 
            this.id = pt.id;
        if (pt.endChar > this.endChar) 
            this.endChar = pt.endChar;
    }
    
    removeStart(len) {
        if (this.text.length <= len) 
            return null;
        let b = new UnitextPlaintext();
        b.parent = this.parent;
        b.beginChar = this.beginChar;
        b.endChar = (b.beginChar + len) - 1;
        b.text = this.text.substring(0, 0 + (b.endChar - b.beginChar) + 1);
        b.typ = this.typ;
        if (this.id !== null) 
            b.id = (this.id + "_" + b.beginChar + "_" + b.endChar);
        else 
            b.id = ("txtS_" + b.beginChar + "_" + b.endChar);
        if (this.layout !== null) {
            if (this.layout.length <= len) 
                this.layout = null;
            else {
                b.layout = Array(len).fill(null);
                for (let i = 0; (i < len) && (i < this.layout.length); i++) {
                    b.layout[i] = this.layout[i];
                }
                let lay = Array(this.layout.length - len).fill(null);
                for (let i = 0; i < lay.length; i++) {
                    lay[i] = this.layout[len + i];
                }
                this.layout = lay;
            }
        }
        let le = (b.endChar - b.beginChar) + 1;
        this.text = this.text.substring(le);
        this.beginChar += le;
        return b;
    }
    
    removeEnd(len) {
        let e = new UnitextPlaintext();
        e.parent = this.parent;
        e.beginChar = (this.endChar + 1) - len;
        e.endChar = (e.beginChar + len) - 1;
        let dd = (((this.endChar - this.beginChar) + 1)) - (((e.endChar - e.beginChar) + 1));
        if (dd >= this.text.length) 
            return null;
        e.text = this.text.substring(dd);
        e.typ = this.typ;
        if (this.id !== null) 
            e.id = (this.id + "_" + e.beginChar + "_" + e.endChar);
        else 
            e.id = ("txtE_" + e.beginChar + "_" + e.endChar);
        if (this.layout !== null) {
            e.layout = Array(len).fill(null);
            for (let i = 0; i < len; i++) {
                let j = (this.layout.length - len) + i;
                if (j >= 0 && (j < this.layout.length)) 
                    e.layout[i] = this.layout[j];
            }
            if ((this.layout.length - len) > 0) {
                let lay = Array(this.layout.length - len).fill(null);
                for (let i = 0; i < lay.length; i++) {
                    if (i < this.layout.length) 
                        lay[i] = this.layout[i];
                }
                this.layout = lay;
            }
            else 
                this.layout = null;
        }
        this.endChar -= len;
        this.text = this.text.substring(0, 0 + (this.endChar - this.beginChar) + 1);
        return e;
    }
    
    toString() {
        let ttt = Utils.trimStartString(((this.text != null ? this.text : "")));
        if (ttt.length > 100) 
            ttt = ttt.substring(0, 0 + 100) + "...";
        if (this.typ === UnitextPlaintextType.SIMPLE) 
            return ("'" + ttt + "'");
        else if (this.typ === UnitextPlaintextType.GENERATED) 
            return ("[" + ttt + "]");
        else 
            return ("<" + ttt + ">");
    }
    
    getPlaintext(res, pars) {
        if (pars !== null && pars.setPositions) {
            this.beginChar = res.length;
            if (this.beginChar === 793) {
            }
        }
        if (pars !== null && !pars.keepIgnored && ((this.ignorable || pars.ignoreLevel > 0))) {
            for (let i = 0; i < this.text.length; i++) {
                res.append(' ');
            }
        }
        else if (pars !== null && pars.supTemplate !== null && this.typ === UnitextPlaintextType.SUP) {
            let txt = ((this.text != null ? this.text : "")).trim();
            if (!Utils.isNullOrEmpty(txt)) 
                res.append(Utils.replaceString(pars.supTemplate, "%1", txt));
        }
        else if (pars !== null && pars.subTemplate !== null && this.typ === UnitextPlaintextType.SUB) {
            let txt = ((this.text != null ? this.text : "")).trim();
            if (!Utils.isNullOrEmpty(txt)) 
                res.append(Utils.replaceString(pars.subTemplate, "%1", txt));
        }
        else if (this.text !== null && this.typ !== UnitextPlaintextType.XML) {
            let txt = this.text;
            if (pars !== null && pars.pageBreak !== null) {
                if (pars.pageBreak.length === 1 && txt.indexOf(pars.pageBreak[0]) >= 0) 
                    txt = Utils.replaceString(txt, pars.pageBreak[0], ' ');
            }
            res.append(txt);
        }
        if (pars !== null && pars.setPositions) 
            this.endChar = res.length - 1;
    }
    
    _findStyle(_id) {
        for (let it = this.parent; it !== null; it = it.parent) {
            let doc = Utils.as(it, UnitextDocument);
            if (doc !== null) {
                if (_id < doc.styles.length) 
                    return doc.styles[_id];
            }
        }
        return null;
    }
    
    getHtml(res, par) {
        if (!par.callBefore(this, res)) 
            return;
        let outSpan = false;
        if (par !== null && this.id !== null && par.styles.containsKey(this.id)) {
            res.append("<span style=\"").append(par.styles.get(this.id)).append("\" id=\"").append(this.id).append("\"");
            outSpan = true;
        }
        else if (this.id !== null) {
            res.append("<span id=\"").append(this.id).append("\"");
            outSpan = true;
        }
        if (par !== null && par.outBeginEndChars && this.beginChar <= this.endChar) {
            if (!outSpan) 
                res.append("<span");
            outSpan = true;
            res.append(" bc=\"").append(this.beginChar).append("\" ec=\"").append(this.endChar).append("\"");
        }
        if (outSpan) 
            res.append('>');
        if (this.typ === UnitextPlaintextType.SUB) 
            res.append("<SUB>");
        else if (this.typ === UnitextPlaintextType.SUP) 
            res.append("<SUP>");
        let textOuted = false;
        if ((par !== null && par.outStyles && this.getStyledFragment(-1) !== null) && this.endChar >= this.beginChar) {
            let map = Array((this.endChar + 1) - this.beginChar).fill(null);
            let hasInline = false;
            for (let i = this.beginChar; i <= this.endChar; i++) {
                let ff = this.getStyledFragment(i);
                if (ff === null || (ff.styleId < 0) || ff.style === null) 
                    continue;
                if (ff.typ === UnitextStyledFragmentType.INLINE) {
                }
                else if (ff.beginChar >= this.beginChar && ff.endChar <= this.endChar) {
                    if (this.parent !== null && this.parent.getStyledFragment(i) === ff) 
                        continue;
                }
                else 
                    continue;
                hasInline = true;
                map[i - this.beginChar] = ff;
            }
            if (hasInline) {
                textOuted = true;
                let cur = null;
                for (let i = 0; (i < map.length) && (i < this.text.length); i++) {
                    if (map[i] === null) {
                        if (cur !== null) {
                            cur = null;
                            res.append("</span>");
                        }
                    }
                    else if (cur !== map[i]) {
                        if (cur !== null) {
                            cur = null;
                            res.append("</span>");
                        }
                        cur = map[i];
                        res.append("<span style=\"");
                        cur.style.getHtml(res);
                        res.append("\">");
                    }
                    MiscHelper.correctHtmlChar(res, this.text[i]);
                }
                if (cur !== null) {
                    cur = null;
                    res.append("</span>");
                }
            }
        }
        if (!textOuted) 
            MiscHelper.correctHtmlValue(res, this.text, false, false, false);
        if (this.typ === UnitextPlaintextType.SUB) 
            res.append("</SUB>");
        else if (this.typ === UnitextPlaintextType.SUP) 
            res.append("</SUP>");
        if (outSpan) 
            res.append("</span>");
        par.callAfter(this, res);
    }
    
    getXml(xml) {
        xml.writeStartElement("text");
        this._writeXmlAttrs(xml);
        if (this.typ !== UnitextPlaintextType.SIMPLE) 
            xml.writeAttributeString("type", this.typ.toString().toLowerCase());
        if (this.layout !== null && this.layout.length > 0) {
            let tmp = new StringBuilder();
            for (let i = 0; i < this.layout.length; i++) {
                if (this.layout[i] === null || this.layout[i].page === null) 
                    continue;
                let j = 0;
                for (j = i + 1; j < this.layout.length; j++) {
                    if (this.layout[i] !== this.layout[j]) 
                        break;
                }
                let page = this.layout[i].page;
                let n = page.rects.indexOf(this.layout[i]);
                if (n < 0) 
                    continue;
                if (tmp.length > 0) 
                    tmp.append(";");
                tmp.append(page.number).append(" ").append(n).append(" ").append((j - i));
                i = j - 1;
            }
            if (tmp.length > 0) 
                xml.writeAttributeString("layout", tmp.toString());
        }
        let txt = MiscHelper.correctXmlValue(this.text);
        let sp = 0;
        for (const ch of txt) {
            if (ch !== ' ') 
                break;
            else 
                sp++;
        }
        if (sp > 0 && sp === txt.length) 
            xml.writeAttributeString("spaces", sp.toString());
        try {
            xml.writeString(MiscHelper.correctXmlValue(txt));
        } catch (ex) {
        }
        xml.writeEndElement();
    }
    
    fromXml(xml) {
        super.fromXml(xml);
        let sp = 0;
        if (xml.attributes !== null) {
            for (const a of xml.attributes) {
                if (a.local_name === "type") {
                    try {
                        this.typ = UnitextPlaintextType.of(a.value);
                    } catch (ex620) {
                    }
                }
                else if (a.local_name === "spaces") {
                    let wrapsp621 = new RefOutArgWrapper();
                    Utils.tryParseInt(a.value, wrapsp621);
                    sp = wrapsp621.value;
                }
                else if (a.local_name === "layout") {
                    let doc = null;
                    for (let it = this.parent; it !== null; it = it.parent) {
                        if (it instanceof UnitextDocument) {
                            doc = Utils.as(it, UnitextDocument);
                            break;
                        }
                    }
                    if (doc === null || doc.pages.length === 0) 
                        continue;
                    let lays = new Array();
                    for (const xx of Utils.splitString(a.value, ';', false)) {
                        let nn = Utils.splitString(xx, ' ', false);
                        if (nn.length !== 3) 
                            continue;
                        let pp = 0;
                        let ll = 0;
                        let cou = 0;
                        let wrappp626 = new RefOutArgWrapper();
                        let inoutres627 = Utils.tryParseInt(nn[0], wrappp626);
                        pp = wrappp626.value;
                        if (!inoutres627) 
                            continue;
                        let wrapll624 = new RefOutArgWrapper();
                        let inoutres625 = Utils.tryParseInt(nn[1], wrapll624);
                        ll = wrapll624.value;
                        if (!inoutres625) 
                            continue;
                        let wrapcou622 = new RefOutArgWrapper();
                        let inoutres623 = Utils.tryParseInt(nn[2], wrapcou622);
                        cou = wrapcou622.value;
                        if (!inoutres623) 
                            continue;
                        if ((pp < 1) || pp > doc.pages.length) 
                            continue;
                        let page = doc.pages[pp - 1];
                        if ((ll < 0) || ll >= page.rects.length) 
                            continue;
                        for (; cou > 0; cou--) {
                            lays.push(page.rects[ll]);
                        }
                    }
                    if (lays.length > 0) 
                        this.layout = lays;
                }
            }
        }
        this.text = xml.inner_text;
        if (sp === 1) 
            this.text = " ";
        else if (sp === 2) 
            this.text = "  ";
        else if (sp > 2) {
            let tmp = new StringBuilder();
            for (let i = 0; i < sp; i++) {
                tmp.append(' ');
            }
            this.text = tmp.toString();
        }
    }
    
    correct(_typ, data) {
        const UnitextCorrHelper = require("./internal/uni/UnitextCorrHelper");
        if (_typ === LocCorrTyp.NPSP2SP) 
            this.text = UnitextCorrHelper.corrNbsp(this.text);
        else if (_typ === LocCorrTyp.TRIMEND) {
            this.text = Utils.trimEndString(this.text);
            if (this.endChar > 0) 
                this.endChar = (this.beginChar + this.text.length) - 1;
        }
    }
    
    setDefaultTextPos(cp, res) {
        this.beginChar = cp.value;
        cp.value += this.text.length;
        this.endChar = cp.value - 1;
        if (res !== null) 
            res.append(this.text);
    }
    
    static _new57(_arg1) {
        let res = new UnitextPlaintext();
        res.text = _arg1;
        return res;
    }
    
    static _new58(_arg1, _arg2) {
        let res = new UnitextPlaintext();
        res.text = _arg1;
        res.typ = _arg2;
        return res;
    }
    
    static _new89(_arg1, _arg2) {
        let res = new UnitextPlaintext();
        res.text = _arg1;
        res.tag = _arg2;
        return res;
    }
    
    static _new352(_arg1, _arg2) {
        let res = new UnitextPlaintext();
        res.text = _arg1;
        res.pageSectionId = _arg2;
        return res;
    }
    
    static _new370(_arg1, _arg2, _arg3, _arg4) {
        let res = new UnitextPlaintext();
        res.text = _arg1;
        res.typ = _arg2;
        res.pageSectionId = _arg3;
        res.m_StyledFrag = _arg4;
        return res;
    }
    
    static _new372(_arg1, _arg2, _arg3) {
        let res = new UnitextPlaintext();
        res.text = _arg1;
        res.typ = _arg2;
        res.m_StyledFrag = _arg3;
        return res;
    }
    
    static _new390(_arg1, _arg2) {
        let res = new UnitextPlaintext();
        res.typ = _arg1;
        res.text = _arg2;
        return res;
    }
    
    static _new399(_arg1) {
        let res = new UnitextPlaintext();
        res.parent = _arg1;
        return res;
    }
    
    static _new611(_arg1, _arg2, _arg3) {
        let res = new UnitextPlaintext();
        res.text = _arg1;
        res.beginChar = _arg2;
        res.endChar = _arg3;
        return res;
    }
}


module.exports = UnitextPlaintext