using System;
using System.Text;
using System.Drawing;
namespace DevComponents.DotNetBar.Presentation
{
    internal class Shape
    {
        #region Private Variables
        private Location m_Location = new Location();
        private SizeInfo m_Size = new SizeInfo();
        private ShapeCollection m_Children = null;
        private PaddingInfo m_Padding = null;
        private bool m_SetChildClip = false;
        #endregion
        #region Internal Implementation
        /// 
        /// Gets the location of the shape.
        /// 
        public Location Location
        {
            get { return m_Location; }
        }
        /// 
        /// Gets the size of the shape.
        /// 
        public SizeInfo Size
        {
            get { return m_Size; }
        }
        /// 
        /// Gets the shape padding. Padding is the inside spacing between shape and it's child shapes.
        /// 
        public PaddingInfo Padding
        {
            get { return m_Padding; }
            set
            {
                m_Padding = value;
            }
        }
        /// 
        /// Gets the collection of child shapes.
        /// 
        public ShapeCollection Children
        {
            get
            {
                if (m_Children == null)
                    m_Children = new ShapeCollection();
                return m_Children;
            }
        }
        /// 
        /// Gets or sets whether this shape will set the ShapePaintInfo.ChildContentClip property to the region that represents the inside content of the shape.
        /// This is used when there is inside content of the shape which is not part of the shape itself and calling routine needs
        /// access to the region that defines the shape inside bounds.
        /// 
        public bool SetChildClip
        {
            get { return m_SetChildClip; }
            set { m_SetChildClip = value; }
        }
        /// 
        /// Paints the shape on canvas. If overriden base implementation must be called to paint any child shapes.
        /// 
        /// Shape paint information.
        public virtual void Paint(ShapePaintInfo p)
        {
            if (m_Children != null && m_Children.Count > 0)
            {
                System.Drawing.Rectangle originalBounds = p.Bounds;
                System.Drawing.Rectangle bounds = new System.Drawing.Rectangle(this.GetLocation(p.Bounds), this.GetSize(p.Bounds));
                if (m_Padding != null)
                {
                    bounds.Width -= m_Padding.HorizontalPadding;
                    bounds.Height -= m_Padding.VerticalPadding;
                    bounds.X += m_Padding.Left;
                    bounds.Y += m_Padding.Top;
                }
                p.Bounds = bounds;
                Region clip = ClipChildren(p.Graphics, bounds);
                if (m_SetChildClip && p.Graphics.Clip!=null)
                {
                    p.ChildContentClip = p.Graphics.Clip as Region;
                }
                foreach (Shape shape in m_Children)
                {
                    shape.Paint(p);
                }
                if (p.ChildContentClip != null)
                {
                    p.ChildContentClip.Dispose();
                    p.ChildContentClip = null;
                }
                if (clip != null)
                {
                    p.Graphics.Clip = clip;
                    clip.Dispose();
                }
                else
                    p.Graphics.ResetClip();
                p.Bounds = originalBounds;
                if (clip != null) clip.Dispose();
            }
        }
        protected virtual Region ClipChildren(Graphics g, System.Drawing.Rectangle childBounds)
        {
            Region clip = g.Clip;
            g.SetClip(childBounds);
            return clip;
        }
        /// 
        /// Returns absolute location of the shape based on parent bounds.
        /// 
        /// Parent absolute bounds.
        /// Absolute location of the shape
        protected virtual Point GetLocation(System.Drawing.Rectangle bounds)
        {
            return GetLocation(bounds, m_Location);
        }
        protected virtual Point GetLocation(System.Drawing.Rectangle bounds, Location refLocation)
        {
            Point loc = bounds.Location;
            if (refLocation.RelativeX == eRelativeLocation.Right)
                loc.X = bounds.Right;
            else if (refLocation.RelativeX == eRelativeLocation.Top)
                loc.X = bounds.Y;
            else if (refLocation.RelativeX == eRelativeLocation.Bottom)
                loc.X = bounds.Bottom;
            if (refLocation.RelativeY == eRelativeLocation.Bottom)
                loc.Y = bounds.Bottom;
            else if (refLocation.RelativeY == eRelativeLocation.Right)
                loc.Y = bounds.Right;
            else if (refLocation.RelativeY == eRelativeLocation.Left)
                loc.Y = bounds.X;
            loc.Offset(refLocation.X, refLocation.Y);
            return loc;
        }
        /// 
        /// Returns absolute size of the shape based on the parent bounds.
        /// 
        /// Absolute parent bounds.
        /// Absolute size of the shape.
        protected virtual Size GetSize(System.Drawing.Rectangle bounds)
        {
            Size size = bounds.Size;
            if (m_Size.RelativeWidth == eRelativeSize.Width)
                size.Width = bounds.Width + m_Size.Width;
            else if (m_Size.RelativeWidth == eRelativeSize.Height)
                size.Width = bounds.Height + m_Size.Height;
            else if (m_Size.Width != 0)
                size.Width = m_Size.Width;
            if (m_Size.RelativeHeight == eRelativeSize.Height)
                size.Height = bounds.Height + m_Size.Height;
            else if (m_Size.RelativeHeight == eRelativeSize.Width)
                size.Height = bounds.Width + m_Size.Height;
            else if (m_Size.Height != 0)
                size.Height = m_Size.Height;
            return size;
        }
        /// 
        /// Gets the absolute bounds of the shape.
        /// 
        /// Parent bounds.
        /// Absolute bounds of the shape.
        protected virtual System.Drawing.Rectangle GetBounds(System.Drawing.Rectangle parentBounds)
        {
            return new System.Drawing.Rectangle(GetLocation(parentBounds), GetSize(parentBounds));
        }
        #endregion
    }
}