using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Hanna.Controls
{
	/// <summary>
	/// Summary description for Polygon.
	/// </summary>
	public class Polygon : Shape
	{
		private const int DEFAULT_POLYGON_SIDES = 3;
		private const int DEFAULT_ORIENTATION = 0;

		private int _polygonalSides	= DEFAULT_POLYGON_SIDES;
		private int _orientationDegree = DEFAULT_ORIENTATION;

		#region construct/dispose/init

		public Polygon()
		{
			InitializeComponent();
		}

		/// <summary> 
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		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()
		{
			// 
			// Polygon
			// 
			this.Name = "Polygon";
			this.Size = new System.Drawing.Size(64, 64);

		}
		#endregion

		#region polygon-specific public decoration members

		public int OrientationDegree
		{
			get
			{	
				return this._orientationDegree;
			}
			set
			{
				if ( this._orientationDegree != value )
				{
					this._orientationDegree = value;
					this.SetRegion();					
					this.Invalidate();
				}
			}
		}
		public int PolygonSides
		{
			get
			{	
				return this._polygonalSides;
			}
			set
			{
				if ( this._polygonalSides != value )
				{
					if ( value < 3 )
						throw new ArgumentException("Polygons must have at least three sides");
					else
					{
						this._polygonalSides = value;
						this.SetRegion();
						this.Invalidate();
					}
				}	
			}
		}

		#endregion 

		#region overrides 

		protected override GraphicsPath GetShapePath(Rectangle rect)
		{
			if ( rect.IsEmpty )
				rect = this.ClientRectangle;
			GraphicsPath path = new GraphicsPath();
			PointF[] ptArray = GetPolygonPoints( this._orientationDegree, rect );
			path.AddPolygon(ptArray);
			return path;
		}

		#endregion 

		#region private drawing extensions and helpers

		private PointF[] GetPolygonPoints(float StartAngleDegree, 
										  Rectangle rect )
		{
			// insure no div by zero error
			if ( this._polygonalSides < DEFAULT_POLYGON_SIDES )
				 this._polygonalSides = DEFAULT_POLYGON_SIDES ;

			float xRad		  = rect.Width/2;
			float yRad		  = rect.Height/2;
			
			float angle		  = DegreeToRadians ( StartAngleDegree );
			float increment   = DegreeToRadians ( 360 / this._polygonalSides );
                        
			ArrayList rtnArray = new ArrayList();

			for ( int idx = 0; idx < this._polygonalSides; idx++)
			{
				PointF pt = new PointF (rect.X + (float)Math.Cos(angle)*xRad+xRad, 
					rect.Y + (float)Math.Sin(angle)*yRad+yRad);
				rtnArray.Add(pt);
				angle += increment;				
			}
			return (PointF[])rtnArray.ToArray(typeof(PointF));
		}

		private float DegreeToRadians(float Degrees)
		{	
			return (float) Degrees * (float)(Math.PI/180);
		}
		#endregion 

	}
}
