using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Hanna.Controls
{
	public enum IconShapes
	{
		Close,
		Restore,
		Maximize, 
		Up,
		Down,
		Left,
		Right,
		DownAll,
		UpAll,
		FastForward,
		FastRewind
	}

	/// <summary>
	/// Summary description for IconShape.
	/// </summary>
	public class IconShape : Shape
	{
		private IconShapes		_iconShape;
		private int				_lineWidth;
		
		#region construct/init/dispose/load
		private System.ComponentModel.Container components = null;
		public IconShape()
		{
			InitializeComponent();
		}
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		#endregion

		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.SuspendLayout();
			// 
			// IconShape
			// 
			this.Name = "IconShape";
			this.Size = new System.Drawing.Size(64, 40);
			this.ResumeLayout(false);

		}
		#endregion

		#region overrides

		protected override GraphicsPath GetShapePath(Rectangle rectangle)
		{
			GraphicsPath path = new GraphicsPath();
         Rectangle rect = this.ClientRectangle;
         if ( ( this.BorderStyle != BorderStyles.None ) &&
					 ( this.BorderWidth > 0 ) )
            rect.Inflate( -(this.BorderWidth*2), -(this.BorderWidth*2) );

			switch ( this._iconShape )
			{
				case IconShapes.Close:
					DrawClose ( path, rect );
					break;
				case IconShapes.Maximize:
					DrawMaximize ( path, rect );
					break;
				case IconShapes.Restore:
					DrawRestore ( path, rect );
					break;
				case IconShapes.Up:
					DrawUp ( path, rect );
					break;
				case IconShapes.Down:
					DrawDown ( path, rect );
					break;
				case IconShapes.Left:
					DrawLeft ( path, rect );
					break;
				case IconShapes.Right:
					DrawRight ( path, rect );
					break;
				case IconShapes.UpAll:
					DrawUpAll ( path, rect );
					break;
				case IconShapes.DownAll:
					DrawDownAll ( path, rect );
					break;
				case IconShapes.FastForward:
					DrawFastForward ( path, rect );
					break;
				case IconShapes.FastRewind:
					DrawFastRewind ( path, rect );
					break;
			}		
			return path;
		}
	
      protected override void SetShapeRegion  ()
      {			
         Rectangle rect = this.ClientRectangle;
         Region tmpRegion = new Region(GetShapePath(this.ClientRectangle));

         if ( this.Region != null )
            this.Region.Dispose();

         if ( ( this.BorderStyle != BorderStyles.None ) &&
            ( this.BorderWidth > 0 ) )
         {
            tmpRegion = new Region(GetShapePath(rect));

            using ( GraphicsPath tmpPath = GetShapePath(rect))
            {
               using ( Pen p = new Pen(this.LineBrush, this.BorderWidth) )
               {
                  tmpPath.Widen(p);
               }
               tmpRegion.Exclude(tmpPath);
               tmpRegion.Union(tmpPath);
            }
         }
         this.Region = tmpRegion;
      }


      #endregion
		
		#region public members
		public IconShapes Icon
		{
			get
			{
				return this._iconShape;
			}
			set 
			{
				if ( this._iconShape != value )
				{
					this._iconShape = value;
					this.SetRegion();
					this.Invalidate();
				}
			}
		}
		public int LineWidth
		{
			get { return this._lineWidth; }
			set 
			{ 
				if ( this._lineWidth != value )
				{
					this._lineWidth = value;
					this.SetRegion();
					this.Invalidate();
				}
			}
		}
		public void SetClientRectangle(Size size, Point location)
		{
			if (! this.Size.Equals(size) || ! this.Location.Equals(location))
			{
				this.Size = size;
				this.Location = location;
				base.SetRegion();
				this.Invalidate();
			}
		}
		#endregion

		#region private drawing helpers

		private int GetRelativeLineWidth()
		{
			int width = System.Math.Min(this.ClientRectangle.Width, this.ClientRectangle.Height);
			width = (int)(width / 8);
			if ( this._lineWidth >= width )
				width = this._lineWidth;
			width = width/2;
			return width;
		}

		private void DrawPointLines( Point[] Points, GraphicsPath path )
		{
			int lines = Points.GetUpperBound(0);
			path.StartFigure();
			for ( int ctr = 0; ctr < lines ; ctr++)
			{
				path.AddLine(Points[ctr], Points[ctr+1]);
			}
			path.CloseFigure();
		}
		private void DrawClose( GraphicsPath path, Rectangle rect )
		{
			int width = GetRelativeLineWidth();
			Point center = new Point(this.Width/2, this.Height/2) ;
			Point[] pts = new Point[] {
											new Point ( 0, width ),
											new Point ( width, 0 ),
											new Point ( center.X, center.Y - width ),
											new Point ( this.ClientRectangle.Width - width, 0 ),
											new Point ( this.ClientRectangle.Width, width ),
											new Point ( center.X + width, center.Y ),
											new Point ( this.ClientRectangle.Width, this.ClientRectangle.Height - width ),
											new Point ( this.ClientRectangle.Width - width, this.ClientRectangle.Height ),
											new Point ( center.X , center.Y + width ),
											new Point ( width, this.ClientRectangle.Height ), 
											new Point ( 0, this.ClientRectangle.Height - width ),
											new Point ( center.X - width, center.Y ),
											new Point ( 0, width )
									  };
			DrawPointLines(pts,path);
		}
		private void DrawMaximize( GraphicsPath path , Rectangle rectangle )
		{
			path.StartFigure();
			path.AddRectangle(rectangle);
			Rectangle rect   = new Rectangle(rectangle.Location, rectangle.Size);
			int width = GetRelativeLineWidth();
			rect.Inflate(new Size(-width, -width*2));
			rect.Height+= width;
			path.AddRectangle(rect);
			path.CloseAllFigures();
		}
		private void DrawRestore( GraphicsPath path, Rectangle rectangle )
		{
			float rectSizeOffset = .7F;
			float rectPointOffset= .3F;
			Point[] pts = new Point[] {
										  new Point ( rectangle.X + (int)(rectangle.Width * rectPointOffset) , rectangle.Y ),
										  new Point ( rectangle.X + (int)(rectangle.Width)                   , rectangle.Y ),			
										  new Point ( rectangle.X + (int)(rectangle.Width)                   , rectangle.Y + (int)(rectangle.Height * rectSizeOffset)),
										  new Point ( rectangle.X + (int)(rectangle.Width * rectSizeOffset)  , rectangle.Y + (int)(rectangle.Height * rectSizeOffset)),
										  new Point ( rectangle.X + (int)(rectangle.Width * rectSizeOffset)  , rectangle.Y + (int)(rectangle.Height)),	
										  new Point ( rectangle.X                                            , rectangle.Y + (int)(rectangle.Height)),	
										  new Point ( rectangle.X                                            , rectangle.Y + (int)(rectangle.Height * rectPointOffset)),
										  new Point ( rectangle.X + (int)(rectangle.Width*rectPointOffset)   , rectangle.Y + (int)(rectangle.Height * rectPointOffset)),
										  new Point ( rectangle.X + (int)(rectangle.Width*rectPointOffset)   , rectangle.Y ) 
									  };
			DrawPointLines( pts, path );
			Rectangle rect   = new Rectangle(rectangle.X, (int)(rectangle.Height * rectPointOffset), (int)(rectangle.Width * rectSizeOffset), (int)(rectangle.Height * rectSizeOffset));
			int width = GetRelativeLineWidth();
			rect.Inflate(new Size(-width, -width*2));
			rect.Height+= width;
			path.AddRectangle(rect);
		}
		private void DrawUp( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y ),
										  new Point ( rectangle.X + rectangle.Width           , rectangle.Y + rectangle.Height),			
										  new Point ( rectangle.X                             , rectangle.Y + rectangle.Height)
									  };
			DrawPointLines(pts, path);
			}
		private void DrawDown( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y + rectangle.Height),
										  new Point ( rectangle.X                             , rectangle.Y ),			
										  new Point ( rectangle.X + rectangle.Width           , rectangle.Y )
									  };
			DrawPointLines(pts, path);
		}
		private void DrawLeft( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X                    , rectangle.Y + (int)(rectangle.Height/2)),
										  new Point ( rectangle.X + rectangle.Width  , rectangle.Y ),			
										  new Point ( rectangle.X + rectangle.Width  , rectangle.Y + rectangle.Height)
									  };
			DrawPointLines(pts, path);
		}
		private void DrawRight( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X + rectangle.Width  , rectangle.Y + (int)(rectangle.Height/2)),
										  new Point ( rectangle.X                    , rectangle.Y + rectangle.Height),			
										  new Point ( rectangle.X                    , rectangle.Y )
									  };
			DrawPointLines(pts, path);
		}
		private void DrawUpAll( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y ),
										  new Point ( rectangle.X + rectangle.Width           , rectangle.Y + (int)(rectangle.Height / 2) ),
										  new Point ( rectangle.X                             , rectangle.Y + (int)(rectangle.Height / 2) )
									  };
			DrawPointLines(pts, path);			
			pts = new Point[] {
									new Point ( rectangle.X + (int)(rectangle.Width/2) , rectangle.Y + (int)(rectangle.Height / 2)),
									new Point ( rectangle.X + rectangle.Width          , rectangle.Y + rectangle.Height),
									new Point ( rectangle.X                            , rectangle.Y + rectangle.Height)
							  };
			DrawPointLines(pts, path);
		}
		private void DrawDownAll( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y + rectangle.Height),
										  new Point ( rectangle.X + rectangle.Width           , rectangle.Y + (int)(rectangle.Height / 2) ),
										  new Point ( rectangle.X                             , rectangle.Y + (int)(rectangle.Height / 2) )
									  };
			DrawPointLines(pts, path);			
			pts = new Point[] {
								  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y + (int)(rectangle.Height / 2)),
								  new Point ( rectangle.X                             , rectangle.Y ),
								  new Point ( rectangle.X + rectangle.Width           , rectangle.Y )
							  };
			DrawPointLines(pts, path);
		}
		private void DrawFastForward( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X + rectangle.Width         , rectangle.Y + (int)(rectangle.Height / 2)),
										  new Point ( rectangle.X + (int)(rectangle.Width/2), rectangle.Y + rectangle.Height),
										  new Point ( rectangle.X + (int)(rectangle.Width/2), rectangle.Y )
									  };
			DrawPointLines(pts, path);			
			pts = new Point[] {
								  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y + (int)(rectangle.Height / 2)),
								  new Point ( rectangle.X                             , rectangle.Y + rectangle.Height),
								  new Point ( rectangle.X                             , rectangle.Y )
							  };
			DrawPointLines(pts, path);
		}
		private void DrawFastRewind( GraphicsPath path, Rectangle rectangle )
		{
			Point[] pts = new Point[] {
										  new Point ( rectangle.X                             , rectangle.Y + (int)(rectangle.Height / 2)),
										  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y + rectangle.Height),
										  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y )
									  };
			DrawPointLines(pts, path);			
			pts = new Point[] {
								  new Point ( rectangle.X + (int)(rectangle.Width/2)  , rectangle.Y + (int)(rectangle.Height / 2)),
								  new Point ( rectangle.X + rectangle.Width           , rectangle.Y + rectangle.Height),
								  new Point ( rectangle.X + rectangle.Width           , rectangle.Y)
							  };
			DrawPointLines(pts, path);
		}
		#endregion

	}
}

