using System;
using System.Drawing;
using System.Text;
using System.Xml;
#if AdvTree
namespace DevComponents.Tree.TextMarkup
#elif DOTNETBAR
using DevComponents.UI.ContentManager;
namespace DevComponents.DotNetBar.TextMarkup
#elif SUPERGRID
namespace DevComponents.SuperGrid.TextMarkup
#elif LAYOUT
namespace DevComponents.DotNetBar.Layout.TextMarkup
#endif
{
    internal abstract class MarkupElement : IBlockExtended
    {
        #region Private Variables
        private MarkupElementCollection m_Elements = null;
        private MarkupElement m_Parent = null;
        private Rectangle m_Bounds = Rectangle.Empty;
        private bool m_Visible = true;
        private bool m_SizeValid = false;
        private Rectangle m_RenderBounds = Rectangle.Empty;
        #endregion
        #region Internal Implementation
        public MarkupElement()
        {
            m_Elements = new MarkupElementCollection(this);
        }
        /// 
        /// Returns whether markup element is an container so it receives full available size of parent control for layout.
        /// 
        public virtual bool IsBlockContainer
        {
            get { return false; }
        }
        /// 
        /// Returns whether markup element is an block element that always consumes a whole line in layout.
        /// 
        public virtual bool IsBlockElement
        {
            get { return false; }
        }
        /// 
        /// Returns whether layout manager switches to new line after processing this element.
        /// 
        public virtual bool IsNewLineAfterElement
        {
            get { return false; }
        }
        /// 
        /// Returns whether layout manager can start new line with this element.
        /// 
        public virtual bool CanStartNewLine
        {
            get { return true; }
        }
        /// 
        /// Gets the collection of child elements if any for this markup element.
        /// 
        public virtual MarkupElementCollection Elements
        {
            get
            {
                if (m_Elements == null)
                    m_Elements = new MarkupElementCollection(this);
                return m_Elements; 
            }
        }
        internal void InvalidateElementsSize()
        {
            this.IsSizeValid = false;
            if (m_Elements==null || m_Elements.Count == 0)
                return;
            foreach (MarkupElement e in m_Elements)
            {
                e.InvalidateElementsSize();
                e.IsSizeValid = false;
            }
        }
        /// 
        /// Gets or sets whether element size is valid. When size is not valid element Measure method will be called to validate size.
        /// 
        public virtual bool IsSizeValid
        {
            get { return m_SizeValid; }
            set { m_SizeValid = value; }
        }
        /// 
        /// Gets element parent or null if parent is not set.
        /// 
        public virtual MarkupElement Parent
        {
            get { return m_Parent; }
        }
        internal void SetParent(MarkupElement parent)
        {
            m_Parent = parent;
        }
        /// 
        /// Gets or sets actual rendering bounds.
        /// 
        public Rectangle Bounds
        {
            get { return m_Bounds; }
            set { m_Bounds = value; }
        }
        /// 
        /// Gets or sets whether markup element is visible.
        /// 
        public bool Visible
        {
            get { return m_Visible; }
            set { m_Visible = value; }
        }
        private Padding _Margin = new Padding(0);
        /// 
        /// Gets or sets the element margin.
        /// 
        public Padding Margin
        {
            get { return _Margin; }
            set { _Margin = value; }
        }
        /// 
        /// Measures the element given available size.
        /// 
        /// Size available to element
        /// Reference to graphics object
        public abstract void Measure(Size availableSize, MarkupDrawContext d);
        /// 
        /// Measures the end tag of an element. Most implementations do not need to do anything but implementations like the ones
        /// that change color should return state back at this time.
        /// 
        /// 
        /// 
        public virtual void MeasureEnd(Size availableSize, MarkupDrawContext d) { }
        /// 
        /// Renders element.
        /// 
        /// Provides markup drawing context information.
        public abstract void Render(MarkupDrawContext d);
        /// 
        /// Renders element tag end. Most implementations do not need to do anything but mplementations like the ones
        /// that change color should return state back at this time.
        /// 
        /// Provides markup drawing context information.
        public virtual void RenderEnd(MarkupDrawContext d) { }
        /// 
        /// Provides final rectangle to element and lets it arrange it's content given new constraint.
        /// 
        /// Final rectangle.
        /// 
        protected abstract void ArrangeCore(Rectangle finalRect, MarkupDrawContext d);
        /// 
        /// Arranges the element given the final size. Layout is two step process with Measure followed by Arrange.
        /// 
        /// 
        /// 
        public void Arrange(Rectangle finalSize, MarkupDrawContext d)
        {
            this.ArrangeCore(finalSize, d);
        }
        public virtual void ReadAttributes(XmlTextReader reader) { }
        /// 
        /// Gets or sets actual rendered bounds for a give markup element if applicable.
        /// 
        public Rectangle RenderBounds
        {
            get { return m_RenderBounds; }
            set { m_RenderBounds = value; }
        }
        #endregion
    }
}