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

const GetPlaintextParam = require("./GetPlaintextParam");
const MiscHelper = require("./../util/MiscHelper");

/**
 * Базовый класс для всех элементов Unitext: 
 * UnitextPlaintext, UnitextContainer, UnitextTable, UnitextTablecell, UnitextList, UnitextListitem, 
 * UnitextNewline, UnitextPagebreak, UnitextFootnote, UnitextImage, UnitextHyperlink, UnitextComment, 
 * UnitextDocblock и UnitextMisc.
 * Базовый класс элементов Unitext
 * 
 */
class UnitextItem {
    
    constructor() {
        this.tag = null;
        this.beginChar = 0;
        this.endChar = 0;
        this.parent = null;
        this.pageSectionId = null;
        this.sourceInfo = null;
        this.ignorable = false;
        this.id = null;
        this.htmlTitle = null;
        this.extData = null;
        this.m_StyledFrag = null;
    }
    
    // Получить первую непробельную позицию
    getPlaintextNsPos(txt) {
        if (txt !== null) {
            for (let p = this.beginChar; p <= this.endChar && (p < txt.length); p++) {
                if (!Utils.isWhitespace(txt[p])) {
                    if (txt[p] !== (String.fromCharCode(7)) && txt[p] !== (String.fromCharCode(0x1E)) && txt[p] !== (String.fromCharCode(0x1F))) 
                        return p;
                }
            }
        }
        return this.beginChar;
    }
    
    // Получить последнюю непробельную позицию
    getPlaintextNsPos1(txt) {
        if (txt !== null) {
            for (let p = this.endChar; p >= 0 && (p < txt.length); p--) {
                if (!Utils.isWhitespace(txt[p])) {
                    if (txt[p] !== (String.fromCharCode(7)) && txt[p] !== (String.fromCharCode(0x1E)) && txt[p] !== (String.fromCharCode(0x1F))) 
                        return p;
                }
            }
        }
        return this.endChar;
    }
    
    get pageSection() {
        const UnitextDocument = require("./UnitextDocument");
        const UnitextPagesection = require("./UnitextPagesection");
        let _id = null;
        for (let it = this; it !== null; it = it.parent) {
            if (it.pageSectionId !== null && _id === null) 
                _id = it.pageSectionId;
            if (it instanceof UnitextPagesection) 
                return Utils.as(it, UnitextPagesection);
            let doc = Utils.as(it, UnitextDocument);
            if (doc !== null) {
                for (const s of doc.sections) {
                    if (s.id === _id) 
                        return s;
                }
            }
        }
        return null;
    }
    
    clone() {
        return null;
    }
    
    _cloneFrom(it) {
        this.beginChar = it.beginChar;
        this.endChar = it.endChar;
        this.sourceInfo = it.sourceInfo;
        this.htmlTitle = it.htmlTitle;
        this.ignorable = it.ignorable;
        this.id = it.id;
        this.extData = it.extData;
        this.pageSectionId = it.pageSectionId;
    }
    
    /**
     * Сгенерировать плоский текст
     * @param res результат запишет сюда
     * @param pars параметры
     */
    getPlaintext(res, pars) {
        if (pars !== null && pars.setPositions) 
            this.beginChar = res.length;
    }
    
    /**
     * Сгенерировать плоский текст текущего элемента и всех его подэлементов
     * @param pars параметры генерации
     * @return результат
     */
    getPlaintextString(pars = null) {
        const UnitextHelper = require("./internal/uni/UnitextHelper");
        return UnitextHelper.getPlaintext(this, pars);
    }
    
    /**
     * Сгенерировать HTML
     * @param res результат
     * @param par параметры генерации
     */
    getHtml(res, par) {
        
    }
    
    /**
     * Сгенерировать HTML
     * @param par параметры генерации
     * @return результат
     */
    getHtmlString(par = null) {
        let res = new StringBuilder();
        this.getHtml(res, par);
        return res.toString();
    }
    
    getXml(xml) {
        xml.writeStartElement("unknown");
        xml.writeEndElement();
    }
    
    _writeXmlAttrs(xml) {
        if (this.id !== null) 
            xml.writeAttributeString("id", MiscHelper.correctXmlValue(this.id));
        if (this.beginChar > 0 || this.endChar > 0) {
            xml.writeAttributeString("b", this.beginChar.toString());
            xml.writeAttributeString("e", this.endChar.toString());
        }
        if (this.htmlTitle !== null) 
            xml.writeAttributeString("title", MiscHelper.correctXmlValue(this.htmlTitle));
        if (this.pageSectionId !== null) 
            xml.writeAttributeString("section", this.pageSectionId);
        if (this.sourceInfo !== null) 
            xml.writeAttributeString("sourceinfo", MiscHelper.correctXmlValue(this.sourceInfo));
        if (this.ignorable) 
            xml.writeAttributeString("ignored", "true");
    }
    
    fromXml(xml) {
        if (xml.attributes !== null) {
            for (const a of xml.attributes) {
                if (a.local_name === "id") 
                    this.id = a.value;
                else if (a.local_name === "b") 
                    this.beginChar = Utils.parseInt(a.value);
                else if (a.local_name === "e") 
                    this.endChar = Utils.parseInt(a.value);
                else if (a.local_name === "l") 
                    this.endChar = (this.beginChar + Utils.parseInt(a.value)) - 1;
                else if (a.local_name === "t" || a.local_name === "title") 
                    this.htmlTitle = a.value;
                else if (a.local_name === "section") 
                    this.pageSectionId = a.value;
                else if (a.local_name === "sourceinfo") 
                    this.sourceInfo = a.value;
                else if (a.local_name === "ignored") 
                    this.ignorable = a.value === "true";
            }
        }
    }
    
    optimize(isContent, pars) {
        return this;
    }
    
    /**
     * Получить список всех элементов (этот и все нижележащий)
     * @param res 
     */
    getAllItems(res, lev) {
        if (lev > 40) {
        }
        if (res !== null) 
            res.push(this);
    }
    
    get isWhitespaces() {
        return false;
    }
    
    get isInline() {
        return true;
    }
    set isInline(value) {
        return value;
    }
    
    get startsOnNewline() {
        return false;
    }
    
    addPlainTextPos(d) {
        this.beginChar += d;
        this.endChar += d;
    }
    
    correct(typ, data) {
        
    }
    
    get innerTag() {
        return null;
    }
    
    /**
     * Поиск среди текущего элемента и его внутренних элементов
     * @param _id идентификатор для поиска
     * @return результат
     */
    findById(_id) {
        if (this.id === _id) 
            return this;
        return null;
    }
    
    replaceChild(old, ne) {
        return false;
    }
    
    setDefaultTextPos(cp, res) {
        this.beginChar = cp.value;
        this.endChar = cp.value - 1;
    }
    
    /**
     * Получить ссылку на стилевой фрагмент для указанной текстовой позиции. 
     * Отметим, что для элемента BeginChar..EndChar может покрывать или пересекаться 
     * с несколькими стилевыми фрагментами.
     * @param textPos позиция текста в системе BeginChar..EndChar (-1 - для первой позиции текущего элемента)
     * @return фрагмент, наиболее удалённый в иерархии фрагментов и содержащий указанную позицию
     */
    getStyledFragment(textPos = -1) {
        if ((textPos < 0) && this.m_StyledFrag !== null) 
            return this.m_StyledFrag;
        if (textPos < 0) 
            textPos = this.beginChar;
        for (let it = this; it !== null; it = it.parent) {
            if (it.m_StyledFrag !== null) {
                let res = it.m_StyledFrag.findByCharPosition(textPos);
                if (res !== null) {
                    if (this.m_StyledFrag === null) 
                        this.m_StyledFrag = res;
                    return res;
                }
            }
        }
        return null;
    }
    
    static static_constructor() {
        UnitextItem.m_DefParams = new GetPlaintextParam();
    }
}


UnitextItem.static_constructor();

module.exports = UnitextItem