/*
 * 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.Text;
using System.Xml;

namespace Pullenti.Unitext
{
    /// <summary>
    /// Список
    /// </summary>
    public class UnitextList : UnitextItem
    {
        public override UnitextItem Optimize(bool isContent, CreateDocumentParam pars)
        {
            foreach (UnitextListitem it in Items) 
            {
                it.Parent = this;
                it.Optimize(false, pars);
                if ((it.Content is UnitextList) && it.Sublist == null && (it.Content as UnitextList).Level == (Level + 1)) 
                {
                    it.Sublist = it.Content as UnitextList;
                    it.Content = null;
                    continue;
                }
                if (it.Sublist != null) 
                    continue;
                UnitextContainer cnt = it.Content as UnitextContainer;
                if (cnt != null && (cnt.Children[cnt.Children.Count - 1] is UnitextList) && (cnt.Children[cnt.Children.Count - 1] as UnitextList).Level == (Level + 1)) 
                {
                    it.Sublist = cnt.Children[cnt.Children.Count - 1] as UnitextList;
                    cnt.Children.RemoveAt(cnt.Children.Count - 1);
                    it.Content = it.Content.Optimize(true, pars);
                }
            }
            if (Items.Count == 0) 
                return null;
            if (UnorderPrefix == null) 
            {
                string pre = null;
                bool ok = true;
                foreach (UnitextListitem it in Items) 
                {
                    if (it.Prefix != null) 
                    {
                        if (pre == null) 
                            pre = Pullenti.Unitext.Internal.Uni.UnitextHelper.GetPlaintext(it.Prefix, null);
                        else if (pre != Pullenti.Unitext.Internal.Uni.UnitextHelper.GetPlaintext(it.Prefix, null)) 
                        {
                            ok = false;
                            break;
                        }
                    }
                }
                if ((ok && pre != null && pre.Length == 1) && !char.IsLetterOrDigit(pre[0])) 
                {
                    UnorderPrefix = pre;
                    foreach (UnitextListitem it in Items) 
                    {
                        it.Prefix = null;
                    }
                }
            }
            else 
                foreach (UnitextListitem it in Items) 
                {
                    it.Prefix = null;
                }
            if (Items.Count == 1 && (!(Parent is UnitextListitem))) 
            {
                if (this._isAllListItemsSingle()) 
                {
                    UnitextContainer ccc = new UnitextContainer();
                    ccc.Id = Id;
                    ccc.m_StyledFrag = m_StyledFrag;
                    for (UnitextList li = this; li != null; li = li.Items[0].Sublist) 
                    {
                        if (ccc.Children.Count > 0) 
                            ccc.Children.Add(new UnitextNewline());
                        UnitextListitem it = li.Items[0];
                        if (ccc.Id == null) 
                            ccc.Id = it.Id;
                        if (it.Prefix != null && it.Content != null) 
                        {
                            ccc.Children.Add(it.Prefix);
                            ccc.Children.Add(new UnitextPlaintext() { Text = " ", BeginChar = it.Prefix.EndChar, EndChar = it.Prefix.EndChar });
                            ccc.Children.Add(it.Content);
                        }
                        else if (it.Prefix != null) 
                            ccc.Children.Add(it.Prefix);
                        else if (it.Content != null) 
                            ccc.Children.Add(it.Content);
                    }
                    if (Parent is UnitextContainer) 
                    {
                        UnitextContainer par = Parent as UnitextContainer;
                        int i = par.GetChildIndexOf(this);
                        if (i >= 0) 
                        {
                            if (((i + 1) < par.Children.Count) && (((par.Children[i + 1] is UnitextNewline) || (par.Children[i + 1] is UnitextPagebreak)))) 
                            {
                            }
                            else 
                                ccc.Children.Add(new UnitextNewline());
                        }
                    }
                    foreach (UnitextItem ch in ccc.Children) 
                    {
                        ch.Parent = ccc;
                    }
                    return ccc.Optimize(true, pars);
                }
            }
            if (pars != null && pars.CorrectParams.TransformListsToContainers) 
            {
                UnitextContainer cnt = new UnitextContainer();
                cnt.Id = Id;
                cnt.m_StyledFrag = m_StyledFrag;
                foreach (UnitextListitem it in Items) 
                {
                    if (it.Prefix != null) 
                    {
                        cnt.Children.Add(it.Prefix);
                        it.Prefix.Parent = cnt;
                    }
                    if (it.Content != null) 
                    {
                        cnt.Children.Add(it.Content);
                        it.Content = cnt;
                    }
                    if (it.Content != null || it.Prefix != null) 
                    {
                        UnitextNewline nl = new UnitextNewline();
                        cnt.Children.Add(nl);
                        nl.Parent = cnt;
                    }
                    if (it.Sublist != null) 
                    {
                        UnitextItem cnt1 = it.Sublist.Optimize(false, pars);
                        if (cnt1 != null) 
                        {
                            cnt.Children.Add(cnt1);
                            cnt1.Parent = cnt;
                        }
                    }
                }
                return cnt.Optimize(false, pars);
            }
            return this;
        }
        bool _isAllListItemsSingle()
        {
            if (Items.Count > 1) 
                return false;
            UnitextListitem it = Items[0];
            if (it.Sublist == null) 
                return true;
            return it.Sublist._isAllListItemsSingle();
        }
        /// <summary>
        /// Элементы списка
        /// </summary>
        public List<UnitextListitem> Items = new List<UnitextListitem>();
        /// <summary>
        /// Для ненумерованных списков это общий префикс
        /// </summary>
        public string UnorderPrefix;
        /// <summary>
        /// Уровень вложенности (0 - первый)
        /// </summary>
        public int Level = 0;
        public override string ToString()
        {
            return string.Format("{0}List ({1} items, {2} level)", (UnorderPrefix == null ? "" : string.Format("Unordered ({0})", UnorderPrefix)), Items.Count, Level);
        }
        public override UnitextItem Clone()
        {
            UnitextList res = new UnitextList();
            res._cloneFrom(this);
            foreach (UnitextListitem it in Items) 
            {
                res.Items.Add(it.Clone() as UnitextListitem);
            }
            res.UnorderPrefix = UnorderPrefix;
            res.Level = Level;
            return res;
        }
        public override bool StartsOnNewline
        {
            get
            {
                return true;
            }
        }
        public override void GetAllItems(List<UnitextItem> res, int lev)
        {
            if (res != null) 
                res.Add(this);
            foreach (UnitextListitem it in Items) 
            {
                it.Parent = this;
                it.GetAllItems(res, lev + 1);
            }
        }
        public override bool IsInline
        {
            get
            {
                return false;
            }
            set
            {
            }
        }
        internal override string InnerTag
        {
            get
            {
                return "lst";
            }
        }
        public override UnitextItem FindById(string id)
        {
            if (Id == id) 
                return this;
            foreach (UnitextListitem it in Items) 
            {
                UnitextItem res = it.FindById(id);
                if (res != null) 
                    return res;
            }
            return null;
        }
        public override void GetPlaintext(StringBuilder res, GetPlaintextParam pars = null)
        {
            if (pars != null && pars.SetPositions) 
                BeginChar = res.Length;
            foreach (UnitextListitem it in Items) 
            {
                for (int ii = 0; ii < Level; ii++) 
                {
                    res.Append('\t');
                }
                if (it == Items[0] && pars != null && pars.SetPositions) 
                    BeginChar = res.Length;
                if (UnorderPrefix != null) 
                    res.AppendFormat("{0} ", UnorderPrefix);
                it.GetPlaintext(res, pars);
            }
            if (pars != null && pars.SetPositions) 
                EndChar = res.Length - 1;
        }
        public override void GetHtml(StringBuilder res, GetHtmlParam par)
        {
            if (!par.CallBefore(this, res)) 
                return;
            if ((Parent is UnitextContainer) && (Parent as UnitextContainer).Typ == UnitextContainerType.Head && Items.Count == 1) 
            {
                UnitextListitem it = Items[0];
                if (it.Prefix != null) 
                {
                    it.Prefix.GetHtml(res, par);
                    res.Append("&nbsp;");
                }
                if (it.Content != null) 
                    it.Content.GetHtml(res, par);
                if (it.Sublist != null) 
                    it.Sublist.GetHtml(res, par);
            }
            else 
            {
                res.Append("\r\n<UL");
                if (Id != null) 
                {
                    res.AppendFormat(" id=\"{0}\"", Id);
                    if (par != null && par.Styles.ContainsKey(Id)) 
                        res.AppendFormat(" style=\"{0}\"", par.Styles[Id]);
                }
                res.Append(">");
                foreach (UnitextListitem it in Items) 
                {
                    it.GetHtml(res, par);
                }
                res.Append("\r\n</UL>");
            }
            par.CallAfter(this, res);
        }
        public override void GetXml(XmlWriter xml)
        {
            xml.WriteStartElement("list");
            this._writeXmlAttrs(xml);
            if (UnorderPrefix != null) 
                xml.WriteAttributeString("pref", Pullenti.Util.MiscHelper.CorrectXmlValue(UnorderPrefix));
            if (Level > 0) 
                xml.WriteAttributeString("level", Level.ToString());
            foreach (UnitextListitem it in Items) 
            {
                it.GetXml(xml);
            }
            xml.WriteEndElement();
        }
        public override void FromXml(XmlNode xml)
        {
            base.FromXml(xml);
            if (xml.Attributes != null) 
            {
                foreach (XmlAttribute a in xml.Attributes) 
                {
                    if (a.LocalName == "pref") 
                        UnorderPrefix = a.Value;
                    else if (a.LocalName == "level") 
                    {
                        int n;
                        if (int.TryParse(a.Value, out n)) 
                            Level = n;
                    }
                }
            }
            foreach (XmlNode x in xml.ChildNodes) 
            {
                UnitextItem it = Pullenti.Unitext.Internal.Uni.UnitextHelper.CreateItem(x, this);
                if (it is UnitextListitem) 
                    Items.Add(it as UnitextListitem);
            }
        }
        internal override void AddPlainTextPos(int d)
        {
            base.AddPlainTextPos(d);
            foreach (UnitextListitem it in Items) 
            {
                it.AddPlainTextPos(d);
            }
        }
        internal override void Correct(Pullenti.Unitext.Internal.Uni.LocCorrTyp typ, object data)
        {
            foreach (UnitextListitem it in Items) 
            {
                it.Correct(typ, data);
            }
        }
        internal override void SetDefaultTextPos(ref int cp, StringBuilder res)
        {
            BeginChar = cp;
            foreach (UnitextListitem it in Items) 
            {
                it.SetDefaultTextPos(ref cp, res);
                it.Parent = this;
            }
            EndChar = cp - 1;
        }
        /// <summary>
        /// Удалить список из дерева, заменив его на UnitextContainer, развернув его элементы
        /// </summary>
        /// <param name="newlineLen">размер в символах перехода на новую строку</param>
        public bool TransformListToContainer(int newlineLen)
        {
            if (Parent == null) 
                return false;
            if (Parent is UnitextContainer) 
            {
                UnitextContainer cnt0 = Parent as UnitextContainer;
                int i0 = cnt0.GetChildIndexOf(this);
                if (i0 < 0) 
                    return false;
            }
            else if (Parent is UnitextListitem) 
                return false;
            UnitextContainer cnt = new UnitextContainer();
            cnt.BeginChar = BeginChar;
            cnt.EndChar = EndChar;
            cnt.Parent = Parent;
            foreach (UnitextListitem it in Items) 
            {
                if (it.Prefix != null) 
                {
                    cnt.Children.Add(it.Prefix);
                    it.Prefix.Parent = cnt;
                }
                if (it.Content != null) 
                {
                    cnt.Children.Add(it.Content);
                    it.Content = cnt;
                }
                if (it.Content != null || it.Prefix != null) 
                {
                    UnitextNewline nl = new UnitextNewline();
                    nl.Parent = cnt;
                    nl.BeginChar = cnt.Children[cnt.Children.Count - 1].EndChar + 1;
                    nl.EndChar = (nl.BeginChar + newlineLen) - 1;
                    cnt.Children.Add(nl);
                }
                if (it.Sublist != null) 
                {
                    cnt.Children.Add(it.Sublist);
                    it.Sublist.Parent = cnt;
                }
            }
            if (Parent is UnitextContainer) 
            {
                UnitextContainer cnt0 = Parent as UnitextContainer;
                int i0 = cnt0.GetChildIndexOf(this);
                cnt0.Children.RemoveAt(i0);
                cnt0.Children.InsertRange(i0, cnt.Children);
                foreach (UnitextItem it in cnt.Children) 
                {
                    it.Parent = cnt0;
                }
            }
            else if (Parent is UnitextTablecell) 
                (Parent as UnitextTablecell).Content = cnt;
            else if (Parent is UnitextDocument) 
                (Parent as UnitextDocument).Content = cnt;
            return true;
        }
    }
}