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

using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;

namespace Pullenti.Unitext.Internal.Word
{
    class DocTextStyles
    {
        public Dictionary<string, DocTextStyle> m_TextStyles = new Dictionary<string, DocTextStyle>();
        public Pullenti.Unitext.UnitextStyle DefStyle;
        public Dictionary<string, Pullenti.Unitext.UnitextStyle> DefStyles = new Dictionary<string, Pullenti.Unitext.UnitextStyle>();
        public List<Pullenti.Unitext.UnitextStyle> UStyles = new List<Pullenti.Unitext.UnitextStyle>();
        Dictionary<string, Pullenti.Unitext.UnitextStyle> m_UStyles = new Dictionary<string, Pullenti.Unitext.UnitextStyle>();
        public bool Ignore;
        public Pullenti.Unitext.UnitextStyle RegisterStyle(Pullenti.Unitext.UnitextStyle st)
        {
            if (Ignore) 
                return st;
            string key = st.ToString();
            if (string.IsNullOrEmpty(key)) 
                return null;
            Pullenti.Unitext.UnitextStyle res;
            if (m_UStyles.TryGetValue(key, out res)) 
                return res;
            m_UStyles.Add(key, st);
            st.Id = UStyles.Count;
            UStyles.Add(st);
            return st;
        }
        public DocTextStyle GetStyle(XmlNode x, string nam)
        {
            string id = _readAttrVal(x, nam, null);
            if (id == null) 
                return null;
            DocTextStyle res;
            if (!m_TextStyles.TryGetValue(id, out res)) 
                return null;
            return res;
        }
        public DocTextStyle GetStyleById(string id)
        {
            DocTextStyle res;
            if (!m_TextStyles.TryGetValue(id, out res)) 
                return null;
            return res;
        }
        string m_MajorFont;
        string m_MinorFont;
        static string _readAttrVal(XmlNode x, string nam, string nam2 = null)
        {
            if (x.Attributes != null) 
            {
                foreach (XmlAttribute a in x.Attributes) 
                {
                    if (a.LocalName == nam) 
                        return a.Value;
                    else if (nam2 != null && a.LocalName == nam2) 
                        return a.Value;
                }
            }
            return null;
        }
        static string _getSizeVal(string val, bool outCm = false)
        {
            if (val == null) 
                return null;
            foreach (char ch in val) 
            {
                if (char.IsLetter(ch)) 
                    return val;
            }
            double d;
            if (!Pullenti.Util.MiscHelper.TryParseDouble(val, out d)) 
                return val;
            if (outCm) 
            {
                d = Math.Round(d / ((20 * 28.35)), 2);
                return string.Format("{0}cm", Pullenti.Util.MiscHelper.OutDouble(d));
            }
            d = Math.Round(d / 20, 2);
            return string.Format("{0}pt", Pullenti.Util.MiscHelper.OutDouble(d));
        }
        static string _corrColor(string val)
        {
            if (val == null) 
                return null;
            if (val.Length != 6) 
                return val;
            foreach (char ch in val) 
            {
                if (char.IsDigit(ch)) 
                {
                }
                else if (ch >= 'A' && ch <= 'F') 
                {
                }
                else if (ch >= 'a' && ch <= 'f') 
                {
                }
                else 
                    return val;
            }
            return val = "#" + val.ToUpper();
        }
        public void ReadUnitextStyle(XmlNode node, Pullenti.Unitext.UnitextStyle st, bool ignoreFontName = false)
        {
            foreach (XmlNode x in node.ChildNodes) 
            {
                if (x.LocalName == "pStyle" || x.LocalName == "rStyle") 
                {
                    string id = _readAttrVal(x, "val", null);
                    if (m_TextStyles.ContainsKey(id)) 
                        m_TextStyles[id].UStyle.CopyTo(st);
                }
                else if (x.LocalName == "rFonts" && !ignoreFontName) 
                {
                    string nam = _readAttrVal(x, "cs", "ansii");
                    if (nam == null) 
                        nam = _readAttrVal(x, "ascii", "hAnsii");
                    if (nam == null) 
                        nam = st.GetAttr("font-name");
                    bool isBidi = false;
                    if (nam == null) 
                    {
                        foreach (XmlAttribute a in x.Attributes) 
                        {
                            if (a.LocalName.EndsWith("cstheme", StringComparison.OrdinalIgnoreCase) && a.Value.EndsWith("bidi", StringComparison.OrdinalIgnoreCase)) 
                                isBidi = true;
                        }
                        foreach (XmlAttribute a in x.Attributes) 
                        {
                            if (a.LocalName.EndsWith("theme", StringComparison.OrdinalIgnoreCase) && !a.LocalName.EndsWith("asiatheme", StringComparison.OrdinalIgnoreCase)) 
                            {
                                if (isBidi) 
                                    break;
                                if (a.Value.StartsWith("major", StringComparison.OrdinalIgnoreCase)) 
                                    nam = m_MajorFont;
                                else if (a.Value.StartsWith("minor", StringComparison.OrdinalIgnoreCase)) 
                                    nam = m_MinorFont;
                            }
                        }
                    }
                    if (nam == null) 
                    {
                        foreach (XmlAttribute a in x.Attributes) 
                        {
                            if (!a.LocalName.EndsWith("theme", StringComparison.OrdinalIgnoreCase) && !a.LocalName.EndsWith("asia", StringComparison.OrdinalIgnoreCase)) 
                            {
                                nam = a.Value;
                                break;
                            }
                        }
                    }
                    if (!string.IsNullOrEmpty(nam)) 
                        st.AddAttr("font-name", nam, false);
                }
            }
            ReadUnitextStyleExt(node, st, true, false);
        }
        public static void ReadUnitextStyleExt(XmlNode node, Pullenti.Unitext.UnitextStyle st, bool ignoreFontName = false, bool numRegime = false)
        {
            foreach (XmlNode x in node.ChildNodes) 
            {
                if (x.LocalName == "b" && !numRegime) 
                {
                    string val = _readAttrVal(x, "val", null);
                    if (val == "0") 
                        val = "normal";
                    else 
                        val = "bold";
                    st.AddAttr("font-weight", val, false);
                }
                else if (x.LocalName == "i" && !numRegime) 
                {
                    string val = _readAttrVal(x, "val", null);
                    if (val == "0") 
                        st.AddAttr("font-style", "none", false);
                    else 
                        st.AddAttr("font-style", "italic", false);
                }
                else if (x.LocalName == "u" && !numRegime) 
                {
                    string val = _readAttrVal(x, "val", null);
                    if (val == "none") 
                        st.AddAttr("text-decoration", "none", false);
                    else 
                        st.AddAttr("text-decoration", "underline", false);
                }
                else if (x.LocalName == "strike" && !numRegime) 
                {
                    string val = _readAttrVal(x, "val", null);
                    if (val != "0") 
                        st.AddAttr("text-decoration", "line-through", false);
                }
                else if (x.LocalName == "caps" && !numRegime) 
                    st.AddAttr("upper-case", "true", false);
                else if (x.LocalName == "rFonts" && !ignoreFontName) 
                {
                    string nam = _readAttrVal(x, "cs", "ansii");
                    if (nam == null) 
                        nam = _readAttrVal(x, "ascii", "hAnsii");
                    if (nam == null) 
                        nam = st.GetAttr("font-name");
                    if (!string.IsNullOrEmpty(nam)) 
                        st.AddAttr("font-name", nam, false);
                }
                else if (x.LocalName == "sz" && !numRegime) 
                {
                    double d;
                    if (Pullenti.Util.MiscHelper.TryParseDouble(_readAttrVal(x, "val", null), out d)) 
                        st.AddAttr("font-size", string.Format("{0}pt", Pullenti.Util.MiscHelper.OutDouble(d / 2)), false);
                }
                else if (x.LocalName == "highlight" || x.LocalName == "color") 
                {
                    string val = _corrColor(_readAttrVal(x, "val", null));
                    if (val == null || val == "auto") 
                        continue;
                    if (x.LocalName == "color") 
                        st.AddAttr("color", val, false);
                    else 
                        st.AddAttr("background-color", val, false);
                }
                else if (x.LocalName == "shd") 
                {
                    string val = _readAttrVal(x, "color", null);
                    if (val == "auto" || _readAttrVal(x, "val", null) == "clear") 
                        val = _corrColor(_readAttrVal(x, "fill", null));
                    else 
                        val = _corrColor(val);
                    if (val != null && val != "auto") 
                        st.AddAttr("background-color", val, false);
                }
                else if (x.LocalName == "rPr") 
                {
                    if (node.LocalName == "pPr") 
                    {
                    }
                    else 
                        ReadUnitextStyleExt(x, st, ignoreFontName, numRegime);
                }
                else if (x.LocalName == "jc" && !numRegime) 
                {
                    string val = _readAttrVal(x, "val", null);
                    if (val == "start") 
                        val = "left";
                    else if (val == "end") 
                        val = "right";
                    else if (val == "both") 
                        val = "justify";
                    st.AddAttr("text-align", val, false);
                }
                else if (x.LocalName == "vAlign" && !numRegime) 
                {
                    string val = _readAttrVal(x, "val", null);
                    st.AddAttr("vertical-align", val, false);
                }
                else if (x.LocalName == "spacing" && !numRegime) 
                {
                    string tempVal = _readAttrVal(x, "val", null);
                    if (tempVal != null) 
                        st.AddAttr("letter-spacing", _getSizeVal(tempVal, false), false);
                    double d;
                    string rule = _readAttrVal(x, "lineRule", null);
                    foreach (XmlAttribute a in x.Attributes) 
                    {
                        if (a.LocalName == "before" || a.LocalName == "top") 
                            st.AddAttr("margin-top", _getSizeVal(a.Value, false), false);
                        else if (a.LocalName == "after" || a.LocalName == "bottom") 
                            st.AddAttr("margin-bottom", _getSizeVal(a.Value, false), false);
                        else if (a.LocalName == "line") 
                        {
                            if (Pullenti.Util.MiscHelper.TryParseDouble(a.Value, out d)) 
                            {
                                string val = null;
                                if (rule == "auto") 
                                {
                                    d = Math.Round(d / 240, 2);
                                    val = string.Format("{0}", Pullenti.Util.MiscHelper.OutDouble(d));
                                }
                                else if (rule == "exact") 
                                {
                                    d = Math.Round(d / 20, 2);
                                    val = string.Format("{0}pt", Pullenti.Util.MiscHelper.OutDouble(d));
                                    double? pt = Pullenti.Util.SizeunitConverter.Convert(st.GetAttr("font-size"), "pt");
                                    if (pt != null && pt.Value > 0) 
                                        val = Pullenti.Util.MiscHelper.OutDouble(Math.Round(d / pt.Value, 2));
                                }
                                else 
                                {
                                }
                                if (val != null) 
                                    st.AddAttr("line-height", val, false);
                            }
                        }
                    }
                }
                else if (x.LocalName == "tcW") 
                {
                    string val = _readAttrVal(x, "w", null);
                    if (val != null) 
                        st.AddAttr("width", _getSizeVal(val, false), false);
                }
                else if (x.LocalName == "ind") 
                {
                    foreach (XmlAttribute a in x.Attributes) 
                    {
                        if (a.LocalName == "left" || a.LocalName == "start") 
                            st.AddAttr("margin-left", _getSizeVal(a.Value, true), false);
                        else if (a.LocalName == "right" || a.LocalName == "end") 
                            st.AddAttr("margin-right", _getSizeVal(a.Value, true), false);
                        else if (a.LocalName == "firstLine") 
                            st.AddAttr("text-indent", _getSizeVal(a.Value, true), false);
                        else if (a.LocalName == "hanging") 
                            st.AddAttr("text-indent", "-" + _getSizeVal(a.Value, true), false);
                    }
                }
            }
        }
        public void ReadTheme(XmlNode node)
        {
            foreach (XmlNode x1 in node.ChildNodes) 
            {
                foreach (XmlNode x2 in x1.ChildNodes) 
                {
                    if (x2.LocalName == "fontScheme") 
                    {
                        foreach (XmlNode x3 in x2.ChildNodes) 
                        {
                            if (x3.LocalName == "majorFont" || x3.LocalName == "minorFont") 
                            {
                                foreach (XmlNode x4 in x3.ChildNodes) 
                                {
                                    if (x4.LocalName == "latin") 
                                    {
                                        if (x3.LocalName == "majorFont") 
                                            m_MajorFont = _readAttrVal(x4, "typeface", null);
                                        else 
                                            m_MinorFont = _readAttrVal(x4, "typeface", null);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        public void ReadAllStyles(XmlNode node, DocNumStyles nums)
        {
            foreach (XmlNode xnum in node.ChildNodes) 
            {
                if (xnum.LocalName == "style") 
                {
                    bool isNormal = false;
                    foreach (XmlNode x in xnum.ChildNodes) 
                    {
                        if (x.LocalName == "name") 
                        {
                            foreach (XmlAttribute xAttr in x.Attributes) 
                            {
                                if (xAttr.Value == "Normal") 
                                    isNormal = true;
                                break;
                            }
                        }
                    }
                    if (!isNormal) 
                        continue;
                    foreach (XmlNode x in xnum.ChildNodes) 
                    {
                        if (x.LocalName == "rPr") 
                        {
                            DefStyle = new Pullenti.Unitext.UnitextStyle();
                            this.ReadUnitextStyle(x, DefStyle, false);
                        }
                    }
                    if (isNormal) 
                        break;
                }
            }
            if (DefStyle != null) 
            {
                if (!DefStyle.Attrs.ContainsKey("font-name")) 
                {
                    foreach (XmlNode xnum in node.ChildNodes) 
                    {
                        if (xnum.LocalName == "docDefaults") 
                        {
                            foreach (XmlNode x in xnum.ChildNodes) 
                            {
                                if (x.LocalName == "rPrDefault") 
                                {
                                    foreach (XmlNode xx in x.ChildNodes) 
                                    {
                                        if (xx.LocalName == "rPr") 
                                            this.ReadUnitextStyle(xx, DefStyle, false);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (DefStyle == null) 
            {
                foreach (XmlNode xnum in node.ChildNodes) 
                {
                    if (xnum.LocalName == "docDefaults") 
                    {
                        foreach (XmlNode x in xnum.ChildNodes) 
                        {
                            if (x.LocalName == "rPrDefault") 
                            {
                                foreach (XmlNode xx in x.ChildNodes) 
                                {
                                    if (xx.LocalName == "rPr") 
                                    {
                                        DefStyle = new Pullenti.Unitext.UnitextStyle();
                                        this.ReadUnitextStyle(xx, DefStyle, false);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (XmlNode xnum in node.ChildNodes) 
            {
                if (xnum.LocalName == "style" && xnum.Attributes != null && xnum.Attributes.Count >= 1) 
                {
                    string id = _readAttrVal(xnum, "styleId", null);
                    if (id == null || m_TextStyles.ContainsKey(id)) 
                        continue;
                    DocTextStyle sty = new DocTextStyle();
                    sty.Xml = xnum;
                    string typ = _readAttrVal(xnum, "type", null);
                    if (DefStyle != null) 
                        DefStyle.CopyTo(sty.UStyle);
                    if (typ != null && DefStyles.ContainsKey(typ)) 
                        DefStyles[typ].CopyTo(sty.UStyle);
                    m_TextStyles.Add(id, sty);
                    foreach (XmlNode x in xnum.ChildNodes) 
                    {
                        if (x.LocalName == "name") 
                        {
                            if (x.Attributes != null && x.Attributes.Count > 0) 
                                sty.Name = x.Attributes[0].Value;
                            if (sty.Name != null && sty.Name == "Body Text Indent") 
                            {
                            }
                        }
                        else if (x.LocalName == "aliases") 
                        {
                            if (x.Attributes != null && x.Attributes.Count > 0) 
                                sty.Aliases = x.Attributes[0].Value;
                        }
                        else if (x.LocalName == "basedOn") 
                            sty.BasedOn = _readAttrVal(x, "val", null);
                    }
                }
            }
            foreach (KeyValuePair<string, DocTextStyle> kp in m_TextStyles) 
            {
                DocTextStyle sty = kp.Value;
                if (sty.Loaded) 
                    continue;
                if (kp.Key == "XX") 
                {
                }
                if (sty.BasedOn != null && m_TextStyles.ContainsKey(sty.BasedOn)) 
                {
                    DocTextStyle sty0 = m_TextStyles[sty.BasedOn];
                    if (!sty0.Loaded) 
                    {
                        if (sty0.BasedOn != null && m_TextStyles.ContainsKey(sty0.BasedOn)) 
                        {
                            DocTextStyle sty00 = m_TextStyles[sty0.BasedOn];
                            if (!sty00.Loaded) 
                                this._readSingleStyle(sty00);
                            sty0.NumId = sty00.NumId;
                            sty0.NumLvl = sty00.NumLvl;
                            sty00.UStyle.CopyTo(sty0.UStyle);
                        }
                        this._readSingleStyle(sty0);
                    }
                    sty.NumId = sty0.NumId;
                    sty.NumLvl = sty0.NumLvl;
                    sty0.UStyle.CopyTo(sty.UStyle);
                }
                this._readSingleStyle(sty);
                if (sty.NumId != null && nums != null) 
                {
                    Pullenti.Unitext.Internal.Uni.UnitextGenNumStyleEx num = nums.GetStyle(sty.NumId);
                    if (num != null) 
                    {
                        Pullenti.Unitext.Internal.Uni.UniTextGenNumLevel lvl = num.GetLevel(sty.NumLvl);
                        if (lvl != null && lvl.Style != null) 
                        {
                            foreach (KeyValuePair<string, string> a in lvl.Style.Attrs) 
                            {
                                if (!sty.UStyle.Attrs.ContainsKey(a.Key)) 
                                    sty.UStyle.Attrs.Add(a.Key, a.Value);
                            }
                        }
                    }
                }
            }
        }
        void _readSingleStyle(DocTextStyle sty)
        {
            string typ = _readAttrVal(sty.Xml, "type", null);
            foreach (XmlNode x in sty.Xml.ChildNodes) 
            {
                if (x.LocalName == "rPr") 
                {
                    this.ReadUnitextStyle(x, sty.UStyle, sty.IsHeading);
                    if (_readAttrVal(sty.Xml, "default", null) == "1") 
                    {
                        if (!DefStyles.ContainsKey(typ)) 
                            DefStyles.Add(typ, sty.UStyle);
                    }
                }
                else if (x.LocalName == "pPr") 
                {
                    this.ReadUnitextStyle(x, sty.UStyle, false);
                    foreach (XmlNode xx in x.ChildNodes) 
                    {
                        if (xx.LocalName == "numPr") 
                        {
                            foreach (XmlNode xxx in xx.ChildNodes) 
                            {
                                if (xxx.LocalName == "numId" && xxx.Attributes != null) 
                                {
                                    foreach (XmlAttribute a in xxx.Attributes) 
                                    {
                                        if (a.LocalName == "val") 
                                            sty.NumId = a.Value;
                                    }
                                }
                                else if (xxx.LocalName == "ilvl" && xxx.Attributes != null) 
                                {
                                    foreach (XmlAttribute a in xxx.Attributes) 
                                    {
                                        if (a.LocalName == "val") 
                                        {
                                            int ll;
                                            if (int.TryParse(a.Value, out ll)) 
                                                sty.NumLvl = ll;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (sty.IsHeading) 
                sty.UStyle.AddAttr("heading-level", sty.CalcHeadingLevel().ToString(), false);
            sty.Loaded = true;
        }
        public void ReadAllExcelStyles(XmlNode node)
        {
            List<Pullenti.Unitext.Internal.Misc.BorderInfo> brdr = new List<Pullenti.Unitext.Internal.Misc.BorderInfo>();
            Dictionary<string, string> specFrms = new Dictionary<string, string>();
            foreach (XmlNode xx in node.ChildNodes) 
            {
                if (xx.LocalName == "borders") 
                {
                    foreach (XmlNode xxx in xx.ChildNodes) 
                    {
                        if (xxx.LocalName == "border") 
                        {
                            Pullenti.Unitext.Internal.Misc.BorderInfo brd = new Pullenti.Unitext.Internal.Misc.BorderInfo();
                            brdr.Add(brd);
                            foreach (XmlNode y in xxx.ChildNodes) 
                            {
                                if (y.Attributes != null && ((y.Attributes.Count > 0 || y.ChildNodes.Count > 0))) 
                                {
                                    if (y.LocalName == "left") 
                                        brd.Left = true;
                                    else if (y.LocalName == "right") 
                                        brd.Right = true;
                                    else if (y.LocalName == "top") 
                                        brd.Top = true;
                                    else if (y.LocalName == "bottom") 
                                        brd.Bottom = true;
                                }
                            }
                        }
                    }
                }
                else if (xx.LocalName == "numFmts") 
                {
                    foreach (XmlNode xxx in xx.ChildNodes) 
                    {
                        if (xxx.LocalName == "numFmt") 
                        {
                            string cod = null;
                            string frm = null;
                            foreach (XmlAttribute a in xxx.Attributes) 
                            {
                                if (a.LocalName == "numFmtId") 
                                    cod = a.Value;
                                else if (a.LocalName == "formatCode") 
                                    frm = a.Value;
                            }
                            if (cod != null && frm != null && !specFrms.ContainsKey(cod)) 
                                specFrms.Add(cod, frm);
                        }
                    }
                }
            }
            foreach (XmlNode x1 in node.ChildNodes) 
            {
                if (x1.LocalName == "cellXfs") 
                {
                    int id = 0;
                    foreach (XmlNode xx in x1.ChildNodes) 
                    {
                        if (xx.LocalName == "xf") 
                        {
                            DocTextStyle st = new DocTextStyle();
                            st.Name = id.ToString();
                            id++;
                            m_TextStyles.Add(st.Name, st);
                            foreach (XmlAttribute a in xx.Attributes) 
                            {
                                if (a.LocalName == "numFmtId") 
                                {
                                    st.XlsFormat = a.Value;
                                    if (specFrms.ContainsKey(a.Value)) 
                                        st.XlsFormat = specFrms[a.Value];
                                }
                                else if (a.LocalName == "borderId") 
                                {
                                    int n;
                                    if (int.TryParse(a.Value, out n)) 
                                    {
                                        if (n >= 0 && (n < brdr.Count)) 
                                            st.XlsBorder = brdr[n];
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}