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

package com.pullenti.unitext;

/**
 * Фрагмент, с которым связаны стили UnitextStyle (если их выделение реализовано для входного формата). 
 * Представляет собой иерархию.
 * Стилевой фрагмент
 */
public class UnitextStyledFragment {

    /**
     * Ссылка на родителя в иерархии
     */
    public UnitextStyledFragment parent;

    /**
     * Дочерние фрагменты
     */
    public java.util.ArrayList<UnitextStyledFragment> children = new java.util.ArrayList<UnitextStyledFragment>();

    public UnitextDocument getDoc() {
        if (m_Doc != null) 
            return m_Doc;
        if (parent != null) 
            return parent.getDoc();
        return null;
    }

    public UnitextDocument setDoc(UnitextDocument value) {
        m_Doc = value;
        return value;
    }


    private UnitextDocument m_Doc;

    /**
     * Тип фрагмента
     */
    public UnitextStyledFragmentType typ = UnitextStyledFragmentType.UNDEFINED;

    /**
     * Идентификатор стиля (если -1, то явно для фрагмента не задан)
     */
    public int styleId = -1;

    public UnitextStyle getStyle() {
        if (m_Style != null) 
            return m_Style;
        UnitextDocument _doc = getDoc();
        if (_doc == null || _doc.styles == null) 
            return null;
        if (styleId >= 0 && (styleId < _doc.styles.size())) 
            return _doc.styles.get(styleId);
        return null;
    }

    public UnitextStyle setStyle(UnitextStyle value) {
        m_Style = value;
        if (value == null) 
            styleId = -1;
        else 
            styleId = value.id;
        return value;
    }


    private UnitextStyle m_Style;

    /**
     * Начальная позиция в плоском тексте
     */
    public int beginChar = -1;

    /**
     * Конечная позиция в плоском тексте
     */
    public int endChar = -1;

    /**
     * Фрагмент текста. Внимание! Он может отличаться от сгенерированного плоского текста. 
     * Это поле добавлено исключительно для наглядности при визуализации, но сами эти данные 
     * не использовать при обработке.
     */
    public String text;

    /**
     * Используйте произвольным образом (не сериализуется)
     */
    public Object tag;

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        if (typ != UnitextStyledFragmentType.UNDEFINED) {
            res.append(typ.toString()).append(" ");
            res.append("[").append(beginChar).append("..").append(endChar).append("] ");
        }
        if (getStyle() != null) 
            res.append(this.getStyle());
        if (text != null) {
            String txt = (text.length() < 100 ? text : (text.substring(0, 0 + 100) + "..."));
            res.append(" \"").append(txt.replace("\n", "\\n")).append("\"");
        }
        return res.toString();
    }

    /**
     * Найти значение атрибута стиля (от текущего вверх по иерархии, пока не найдём)
     * @param name имя атрибута
     * @param defvalue значение, если не нашли
     * @return значение
     */
    public String getStyleAttr(String name, String defvalue) {
        for (UnitextStyledFragment fr = this; fr != null; fr = fr.parent) {
            if (fr.styleId >= 0) {
                UnitextStyle sty = fr.getStyle();
                if (sty != null) {
                    String res = sty.getAttr(name);
                    if (res != null) 
                        return res;
                }
            }
        }
        return defvalue;
    }

    public UnitextStyledFragment clone() {
        UnitextStyledFragment res = new UnitextStyledFragment();
        res.typ = typ;
        res.styleId = styleId;
        res.setDoc(this.getDoc());
        res.parent = parent;
        res.beginChar = beginChar;
        res.endChar = endChar;
        res.text = text;
        for (UnitextStyledFragment ch : children) {
            UnitextStyledFragment chh = ch.clone();
            chh.parent = res;
            res.children.add(chh);
        }
        return res;
    }

    public void addChild(UnitextStyledFragment ch) {
        ch.parent = this;
        if (children.size() > 0 && (ch.endChar < children.get(0).beginChar)) {
            children.add(0, ch);
            return;
        }
        for (int i = 0; i < (children.size() - 1); i++) {
            if ((children.get(i).endChar < ch.beginChar) && (ch.endChar < children.get(i + 1).beginChar)) {
                children.add(i + 1, ch);
                return;
            }
        }
        children.add(ch);
    }

    public void getXml(com.pullenti.unisharp.XmlWriterWrapper xml, String _tag, boolean outStyleFull) throws javax.xml.stream.XMLStreamException {
        xml.wr.writeStartElement((_tag != null ? _tag : "stylefrag"));
        if (typ != UnitextStyledFragmentType.UNDEFINED) 
            xml.wr.writeAttribute("typ", typ.toString().toLowerCase());
        if (styleId >= 0) 
            xml.wr.writeAttribute("style", ((Integer)styleId).toString());
        xml.wr.writeAttribute("b", ((Integer)beginChar).toString());
        xml.wr.writeAttribute("e", ((Integer)endChar).toString());
        if (styleId >= 0 && getStyle() != null) {
            for (java.util.Map.Entry<String, String> kp : getStyle().attrs.entrySet()) {
                xml.wr.writeAttribute(kp.getKey(), kp.getValue());
            }
        }
        if (text != null) 
            xml.writeElementString("text", com.pullenti.util.MiscHelper.correctXmlValue(text));
        if (!outStyleFull) {
            for (UnitextStyledFragment ch : children) {
                ch.getXml(xml, null, false);
            }
        }
        xml.wr.writeEndElement();
    }

    public void fromXml(org.w3c.dom.Node xml) throws NumberFormatException {
        for (org.w3c.dom.Node a : (new com.pullenti.unisharp.XmlAttrListWrapper(xml.getAttributes())).arr) {
            if (com.pullenti.unisharp.Utils.stringsEq(com.pullenti.unisharp.Utils.getXmlLocalName(a), "typ")) {
                try {
                    typ = (UnitextStyledFragmentType)UnitextStyledFragmentType.of(a.getNodeValue());
                } catch (Exception ex634) {
                }
            }
            else if (com.pullenti.unisharp.Utils.stringsEq(com.pullenti.unisharp.Utils.getXmlLocalName(a), "style")) 
                styleId = com.pullenti.unisharp.Utils.parseInteger(a.getNodeValue(), 0, null);
            else if (com.pullenti.unisharp.Utils.stringsEq(com.pullenti.unisharp.Utils.getXmlLocalName(a), "b")) 
                beginChar = com.pullenti.unisharp.Utils.parseInteger(a.getNodeValue(), 0, null);
            else if (com.pullenti.unisharp.Utils.stringsEq(com.pullenti.unisharp.Utils.getXmlLocalName(a), "e")) 
                endChar = com.pullenti.unisharp.Utils.parseInteger(a.getNodeValue(), 0, null);
        }
        for (org.w3c.dom.Node x : (new com.pullenti.unisharp.XmlNodeListWrapper(xml.getChildNodes())).arr) {
            if (com.pullenti.unisharp.Utils.stringsEq(com.pullenti.unisharp.Utils.getXmlLocalName(x), "stylefrag")) {
                UnitextStyledFragment fr = new UnitextStyledFragment();
                fr.parent = this;
                fr.fromXml(x);
                children.add(fr);
            }
            else if (com.pullenti.unisharp.Utils.stringsEq(com.pullenti.unisharp.Utils.getXmlLocalName(x), "text")) 
                text = x.getTextContent();
        }
    }

    /**
     * Найти самый мелкий в дереве фрагмент (удалённный от корня), 
     * содержащий указанную позицию плоского текста.
     * @param cp позиция символа плоского текста
     * @return фрагмент или null
     */
    public UnitextStyledFragment findByCharPosition(int cp) {
        if ((cp < beginChar) || cp > endChar) 
            return null;
        if (children.size() > 10) {
            int i = children.size() / 2;
            int d = children.size() / 4;
            if (d == 0) 
                d = 1;
            int k = d + 2;
            while (k > 0) {
                if (i >= children.size() || (i < 0)) 
                    break;
                UnitextStyledFragment ch = children.get(i);
                if (ch.beginChar <= cp && cp <= ch.endChar) {
                    UnitextStyledFragment res = ch.findByCharPosition(cp);
                    if (res != null) 
                        return res;
                    return this;
                }
                if (ch.beginChar < cp) 
                    i += d;
                else if (ch.endChar > cp) 
                    i -= d;
                else 
                    i += d;
                d /= 2;
                if (d == 0) {
                    d = 1;
                    k--;
                }
            }
        }
        for (UnitextStyledFragment ch : children) {
            if (ch.beginChar <= cp && cp <= ch.endChar) {
                UnitextStyledFragment res = ch.findByCharPosition(cp);
                if (res != null) 
                    return res;
                return this;
            }
        }
        return this;
    }

    public int dispInline = -1;

    public int lenInline = 0;

    public static UnitextStyledFragment _new449(UnitextStyledFragmentType _arg1, UnitextStyledFragment _arg2) {
        UnitextStyledFragment res = new UnitextStyledFragment();
        res.typ = _arg1;
        res.parent = _arg2;
        return res;
    }

    public static UnitextStyledFragment _new506(UnitextStyledFragment _arg1, UnitextStyledFragmentType _arg2) {
        UnitextStyledFragment res = new UnitextStyledFragment();
        res.parent = _arg1;
        res.typ = _arg2;
        return res;
    }

    public static UnitextStyledFragment _new519(UnitextStyledFragmentType _arg1, UnitextStyle _arg2, UnitextStyledFragment _arg3) {
        UnitextStyledFragment res = new UnitextStyledFragment();
        res.typ = _arg1;
        res.setStyle(_arg2);
        res.parent = _arg3;
        return res;
    }
    public UnitextStyledFragment() {
    }
}
