using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
namespace DevComponents.DotNetBar.Controls
{
    /// 
    /// Data storage class for clock hand visual style.
    /// 
    [Description("Clock Hand Style"),
    TypeConverterAttribute(typeof(ExpandableObjectConverter))]
    public class ClockHandStyleData : INotifyPropertyChanged
    {
        private bool _DrawOverCap;
        /// 
        /// Gets or sets a value indicating whether the hand is drawn over the cap.
        /// 
        [DefaultValue(false),
        Category("Appearance"),
        Description("Indicates whether the hand is drawn over the cap.")]
        public bool DrawOverCap
        {
            get { return _DrawOverCap; }
            set { _DrawOverCap = value; }
        }
        private void ColorPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChanged(e);
        }
        private ColorData _HandColor;
        /// 
        /// Gets or sets the hand color data for this hand.
        /// 
        [Category("Appearance"),
        Description("The hand color data for this hand.")]
        public ColorData HandColor
        {
            get { return _HandColor; }
            set
            {
                if (value != _HandColor)
                {
                    if (_HandColor != null) _HandColor.PropertyChanged -= ColorPropertyChanged;
                    _HandColor = value;
                    if (_HandColor != null) _HandColor.PropertyChanged += ColorPropertyChanged;
                    OnPropertyChanged(new PropertyChangedEventArgs("HandColor"));
                }
            }
        }
        /// 
        /// Resets the property to default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetHandColor()
        {
            HandColor = new ColorData(eBrushTypes.Solid, Color.FromArgb(109, 127, 138), Color.FromArgb(109, 127, 138), Color.FromArgb(128, 109, 127, 138), 0.01f);
        }
        private eHandStyles _HandStyle;
        /// 
        /// Gets or sets the hand style for this clock hand. Default value is Style1.
        /// 
        [DefaultValue(eHandStyles.Style1),
        Category("Appearance"),
        Description("The hand style for this clock hand.")]
        public eHandStyles HandStyle
        {
            get { return _HandStyle; }
            set
            {
                if (value != _HandStyle)
                {
                    _HandStyle = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("HandStyle"));
                }
            }
        }
        private float _Length;
        /// 
        /// Gets or sets the length of this clock hand as a percentage value ranging from 0.0 to 1.0, with 1.0 being half the width/height of the bounding rectangle. Default value is 1.0.
        /// 
        [DefaultValue(1.0f),
        Category("Appearance"),
        Description("The length of this clock hand as a percentage value ranging from 0.0 to 1.0, with 1.0 being half the width/height of the bounding rectangle.")]
        public float Length
        {
            get { return _Length; }
            set
            {
                if (value != _Length)
                {
                    _Length = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Length"));
                }
            }
        }
        private float _Width;
        /// 
        /// Gets or sets the width of this clock hand as a percentage value ranging from 0.0 to 1.0, with 1.0 being half the width/height of the bounding rectangle. Default value is 0.1.
        /// 
        [DefaultValue(0.1f),
        Category("Appearance"),
        Description("The width of this clock hand as a percentage value ranging from 0.0 to 1.0, with 1.0 being half the width/height of the bounding rectangle.")]
        public float Width
        {
            get { return _Width; }
            set
            {
                if (value != _Width)
                {
                    _Width = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Width"));
                }
            }
        }
        /// 
        /// Occurs when property value has changed.
        /// 
        public event PropertyChangedEventHandler PropertyChanged;
        /// 
        /// Initializes a new instance of the ClockHand class.
        /// 
        public ClockHandStyleData()
        {
            _DrawOverCap = false;
            _HandColor = new ColorData(eBrushTypes.Solid, Color.FromArgb(109, 127, 138), Color.FromArgb(109, 127, 138), Color.FromArgb(128, 109, 127, 138), 0.01f);
            _HandStyle = eHandStyles.Style1;
            _Length = 1.0f;
            _Width = 0.1f;
        }
        /// 
        /// Initializes a new instance of the ClockHand class.
        /// 
        /// The hand style for this item.
        /// The length of this clock hand as a percentage value ranging from 0.0 to 1.0, with 1.0 being half the width/height of the bounding rectangle
        /// The width of this clock hand as a percentage value ranging from 0.0 to 1.0, with 1.0 being half the width/height of the bounding rectangle.
        public ClockHandStyleData(eHandStyles handStyle, float length, float width)
        {
            _DrawOverCap = false;
            _HandColor = new ColorData(eBrushTypes.Solid, Color.FromArgb(109, 127, 138), Color.FromArgb(109, 127, 138), Color.FromArgb(128, 109, 127, 138), 0.01f);
            _HandStyle = handStyle;
            _Length = length;
            _Width = width;
        }
        /// 
        /// Indicates whether the specified point is contained within the bounds of this hand.
        /// 
        /// The bounding rectangle of the parent clock control.
        /// The clockwise angle for this clock hand in degrees from the 12 o'clock position.
        /// A Point that represents the point to test.
        /// 
        public virtual bool ContainsPoint(RectangleF boundingRect, float angle, Point pt)
        {
            GraphicsPath path;
            bool ret;
            path = GenerateHandPath(boundingRect, angle);
            
            ret = path.IsVisible(pt);
            path.Dispose();
            return ret;
        }
        /// 
        /// Generates a scaled and rotated graphics path based on the given style, rectangle and angle.
        /// 
        /// The bounding rectangle of the parent clock control.
        /// The clockwise angle for this clock hand in degrees from the 12 o'clock position.
        /// 
        public GraphicsPath GenerateHandPath(RectangleF boundingRect, float angle)
        {
            GraphicsPath path = new GraphicsPath();
            RectangleF rect;
            Matrix matrix;
            float scaleFactor;
            PointF[] pts;
            switch (_HandStyle)
            {
                case eHandStyles.Style1:
                    pts = new PointF[4];
                    pts[0].X = -0.5f;
                    pts[0].Y = 0.0f;
                    pts[1].X = -0.5f;
                    pts[1].Y = -1.0f;
                    pts[2].X = 0.5f;
                    pts[2].Y = -1.0f;
                    pts[3].X = 0.5f;
                    pts[3].Y = 0.0f;
                    path.AddPolygon(pts);
                    break;
                case eHandStyles.Style2:
                    pts = new PointF[4];
                    pts[0].X = -0.4f;
                    pts[0].Y = 0.25f;
                    pts[1].X = -0.4f;
                    pts[1].Y = -1.0f;
                    pts[2].X = 0.4f;
                    pts[2].Y = -1.0f;
                    pts[3].X = 0.4f;
                    pts[3].Y = 0.25f;
                    path.AddPolygon(pts);
                    break;
                case eHandStyles.Style3:
                    pts = new PointF[4];
                    pts[0].X = -0.5f;
                    pts[0].Y = 0.0f;
                    pts[1].X = -0.0125f;
                    pts[1].Y = -1.0f;
                    
                    pts[2].X = 0.0125f;
                    pts[2].Y = -1.0f;
                    pts[3].X = 0.5f;
                    pts[3].Y = 0.0f;
                    path.AddPolygon(pts);
                    break;
                case eHandStyles.Style4:
                    path.FillMode = FillMode.Winding;
                    pts = new PointF[4];
                    pts[0].X = -0.5f;
                    pts[0].Y = -0.05f;
                    pts[1].X = -0.5f;
                    pts[1].Y = -1.0f;
                    pts[2].X = 0.5f;
                    pts[2].Y = -1.0f;
                    pts[3].X = 0.5f;
                    pts[3].Y = -0.05f;
                    path.AddPolygon(pts);
                    rect = new RectangleF(-5.0f, -0.06f, 10.0f, 0.12f);
                    path.AddEllipse(rect);
                    break;
            }
            scaleFactor = Math.Min(boundingRect.Width, boundingRect.Height) / 2.0f;
            matrix = new Matrix();
            matrix.Translate(boundingRect.X + boundingRect.Width * 0.5f, boundingRect.Y + boundingRect.Width * 0.5f);
            matrix.Rotate(angle);
            matrix.Scale(scaleFactor * Width, scaleFactor * Length);
            path.Transform(matrix);
            matrix.Dispose();
            return path;
        }
        /// 
        /// Raises the PropertyChanged event.
        /// 
        /// Event arguments
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }
    }
    /// 
    /// Enumeration containing the available hand styles.
    /// 
    public enum eHandStyles
    {
        /// 
        /// Style 1.
        /// 
        Style1,
        /// 
        /// Style 2.
        /// 
        Style2,
        /// 
        /// Style 3.
        /// 
        Style3,
        /// 
        /// Style 4.
        /// 
        Style4,
    }
}