using System;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using DevComponents.Editors;
using System.Drawing;
namespace DevComponents.DotNetBar.Controls
{
    /// 
    /// Represents the Rating control.
    /// 
    [ToolboxBitmap(typeof(RatingStar), "Controls.RatingStar.ico"), ToolboxItem(true), DefaultEvent("RatingChanged"), System.Runtime.InteropServices.ComVisible(true)]
    public class RatingStar : BaseItemControl, ICommandSource
    {
        #region Private Variables
        private RatingItem _RatingItem = null;
        #endregion
        #region Events
        /// 
        /// Occurs when Rating property has changed.
        /// 
        [Description("Occurs when Rating property has changed.")]
        public event EventHandler RatingChanged;
        /// 
        /// Occurs when RatingValue property has changed.
        /// 
        [Description("Occurs when Rating property has changed.")]
        public event EventHandler RatingValueChanged;
        /// 
        /// Occurs when Rating property is about to be changed and provides opportunity to cancel the change.
        /// 
        [Description("Occurs when Rating property has changed.")]
        public event RatingChangeEventHandler RatingChanging;
        /// 
        /// Occurs when AverageRating property has changed.
        /// 
        [Description("Occurs when AverageRating property has changed.")]
        public event EventHandler AverageRatingChanged;
        /// 
        /// Occurs when AverageRatingValue property has changed.
        /// 
        [Description("Occurs when AverageRatingValue property has changed.")]
        public event EventHandler AverageRatingValueChanged;
        /// 
        /// Occurs when text markup link is clicked. Markup links can be created using "a" tag, for example:
        /// Markup link
        /// 
        public event MarkupLinkClickEventHandler MarkupLinkClick;
        /// 
        /// Occurs when RatingValue property is set and it allows you to provide custom parsing for the values.
        /// 
        public event ParseIntegerValueEventHandler ParseRatingValue;
        /// 
        /// Occurs when AverageRatingValue property is set and it allows you to provide custom parsing for the values.
        /// 
        public event ParseDoubleValueEventHandler ParseAverageRatingValue;
        #endregion
        #region Constructor
        /// 
        /// Initializes a new instance of the Rating class.
        /// 
        public RatingStar()
        {
            this.SetStyle(ControlStyles.Selectable, false);
            _RatingItem = new RatingItem();
            _RatingItem.Style = eDotNetBarStyle.Office2007;
            _RatingItem.RatingChanging += new RatingChangeEventHandler(RatingItemRatingChanging);
            _RatingItem.RatingChanged += new EventHandler(RatingItemRatingChanged);
            _RatingItem.AverageRatingChanged += new EventHandler(RatingItemAverageRatingChanged);
            _RatingItem.ParseAverageRatingValue += new DevComponents.Editors.ParseDoubleValueEventHandler(RatingItemParseAverageRatingValue);
            _RatingItem.ParseRatingValue += new DevComponents.Editors.ParseIntegerValueEventHandler(RatingItemParseRatingValue);
            this.HostItem = _RatingItem;
        }
        #endregion
        #region Internal Implementation
        /// 
        /// Indicates number of stars used for the rating. Minium value is 2 stars.
        /// 
        [DefaultValue(5), Category("Appearance"), Description("Indicates number of stars used for the rating.")]
        public int NumberOfStars
        {
            get { return _RatingItem.NumberOfStars; }
            set
            {
                _RatingItem.NumberOfStars = value;
                if (this.AutoSize) this.AdjustSize();
            }
        }
        /// 
        /// Gets or sets the rating value represented by the control. Default value is 0 which indicates
        /// that there is no rating set. Maximum value is 5.
        /// 
        [DefaultValue(0), Category("Data"), Description("Indicates rating value represented by the control.")]
        public int Rating
        {
            get
            {
                return _RatingItem.Rating;
            }
            set
            {
            	_RatingItem.Rating = value;
            }
        }
        /// 
        /// Gets or sets the average rating shown by control. Control will display average rating (if set) when no explicit
        /// Rating value is set through Rating property. Minimum value is 0 and Maximum value is 5.
        /// 
        [DefaultValue(0d), Category("Data"), Description("Indicates average rating shown by control.")]
        public double AverageRating
        {
            get
            {
                return _RatingItem.AverageRating;
            }
            set
            {
            	_RatingItem.AverageRating = value;
            }
        }
        /// 
        /// Gets or sets the AverageRating property. This property is provided for Data-Binding with NULL value support.
        /// 
        [Bindable(true), Browsable(false), RefreshProperties(RefreshProperties.All), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), System.ComponentModel.TypeConverter(typeof(System.ComponentModel.StringConverter))]
        public object AverageRatingValue
        {
            get
            {
                return _RatingItem.AverageRatingValue;
            }
            set
            {
                _RatingItem.AverageRatingValue = value;
            }
        }
        /// 
        /// Gets the reference to custom rating images.
        /// 
        [Browsable(true), Category("Images"), Description("Gets the reference to custom rating images."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public RatingImages CustomImages
        {
            get { return _RatingItem.CustomImages; }
        }
        /// 
        /// Gets or sets whether text assigned to the check box is visible. Default value is true.
        /// 
        [Browsable(true), DefaultValue(true), Category("Appearance"), Description("Indicates whether text assigned to the check box is visible.")]
        public bool TextVisible
        {
            get { return _RatingItem.TextVisible; }
            set
            {
                _RatingItem.TextVisible = value;
            }
        }
        /// 
        /// Gets or sets whether text-markup support is enabled for items Text property. Default value is true.
        /// Set this property to false to display HTML or other markup in the item instead of it being parsed as text-markup.
        /// 
        [DefaultValue(true), Category("Appearance"), Description("Indicates whether text-markup support is enabled for items Text property.")]
        public bool EnableMarkup
        {
            get { return _RatingItem.EnableMarkup; }
            set
            {
                _RatingItem.EnableMarkup = value;
            }
        }
        /// 
        /// Gets or sets whether rating can be edited. Default value is true.
        /// 
        [DefaultValue(true), Category("Behavior"), Description("Indicates whether rating can be edited.")]
        public bool IsEditable
        {
            get { return _RatingItem.IsEditable; }
            set
            {
                _RatingItem.IsEditable = value;
            }
        }
        /// 
        /// Gets or sets the orientation of rating control.
        /// 
        [DefaultValue(eOrientation.Horizontal), Category("Appearance"), Description("Gets or sets the orientation of rating control.")]
        public eOrientation RatingOrientation
        {
            get { return _RatingItem.RatingOrientation; }
            set
            {
                _RatingItem.RatingOrientation = value;
            }
        }
        /// 
        /// Gets or sets the Rating property value. This property is provided for Data-Binding with NULL value support.
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), RefreshProperties(RefreshProperties.All), Bindable(true)]
        public object RatingValue
        {
            get { return _RatingItem.RatingValue; }
            set
            {
                _RatingItem.RatingValue = value;
            }
        }
        /// 
        /// Gets or sets the text color. Default value is Color.Empty which indicates that default color is used.
        /// 
        [Browsable(true), Category("Appearance"), Description("Indicates text color.")]
        public Color TextColor
        {
            get { return _RatingItem.TextColor; }
            set
            {
                _RatingItem.TextColor = value;
            }
        }
        /// 
        /// Gets or sets the spacing between optional text and the rating.
        /// 
        [DefaultValue(0), Category("Appearance"), Description("Gets or sets the spacing between optional text and the rating.")]
        public int TextSpacing
        {
            get { return _RatingItem.TextSpacing; }
            set
            {
                _RatingItem.TextSpacing = value;
            }
        }
        private void RatingItemParseRatingValue(object sender, DevComponents.Editors.ParseIntegerValueEventArgs e)
        {
            OnParseRatingValue(e);
        }
        /// 
        /// Raises the ParseRating event.
        /// 
        /// Provides event arguments.
        protected virtual void OnParseRatingValue(ParseIntegerValueEventArgs e)
        {
            if (ParseRatingValue != null)
                ParseRatingValue(this, e);
        }
        private void RatingItemParseAverageRatingValue(object sender, DevComponents.Editors.ParseDoubleValueEventArgs e)
        {
            OnParseAverageRatingValue(e);
        }
        /// 
        /// Raises the ParseAverageRatingValue event.
        /// 
        /// Provides event arguments.
        protected virtual void OnParseAverageRatingValue(ParseDoubleValueEventArgs e)
        {
            if (ParseAverageRatingValue != null)
                ParseAverageRatingValue(this, e);
        }
        private void RatingItemAverageRatingChanged(object sender, EventArgs e)
        {
            OnAverageRatingChanged(e);
        }
        /// 
        /// Raises the AverageRatingChanged event.
        /// 
        /// Event data.
        protected virtual void OnAverageRatingChanged(EventArgs eventArgs)
        {
            if (AverageRatingChanged != null) AverageRatingChanged(this, eventArgs);
            if (AverageRatingValueChanged != null) AverageRatingValueChanged(this, eventArgs);
        }
        private void RatingItemRatingChanged(object sender, EventArgs e)
        {
            OnRatingChanged(e);
        }
        /// 
        /// Raises the RatingChanged event.
        /// 
        /// Event data.
        protected virtual void OnRatingChanged(EventArgs eventArgs)
        {
            EventHandler handler = RatingChanged;
            if (handler != null) handler(this, eventArgs);
            handler = RatingValueChanged;
            if (handler != null) handler(this, eventArgs);
        }
        private void RatingItemRatingChanging(object sender, RatingChangeEventArgs e)
        {
            OnRatingChanging(e);
        }
        /// 
        /// Raises RatingChanging event.
        /// 
        /// Event data
        protected virtual void OnRatingChanging(RatingChangeEventArgs e)
        {
            if (RatingChanging != null)
                RatingChanging(this, e);
        }
#if FRAMEWORK20
        [Localizable(true), Browsable(false)]
        public new System.Windows.Forms.Padding Padding
        {
            get { return base.Padding; }
            set { base.Padding = value; }
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
        }
        public override Size GetPreferredSize(Size proposedSize)
        {
            if (!BarFunctions.IsHandleValid(this))
                return base.GetPreferredSize(proposedSize);
            
            _RatingItem.RecalcSize();
            Size s = _RatingItem.CalcSize;
            s.Width += 2;
            s.Height += 2;
            if (!this.TextVisible) s.Width += 2;
            s.Width += ElementStyleLayout.HorizontalStyleWhiteSpace(this.GetBackgroundStyle());
            s.Height += ElementStyleLayout.VerticalStyleWhiteSpace(this.GetBackgroundStyle());
            _RatingItem.Bounds = GetItemBounds();
            return s;
        }
        /// 
        /// Gets or sets a value indicating whether the control is automatically resized to display its entire contents. You can set MaximumSize.Width property to set the maximum width used by the control.
        /// 
        [Browsable(true), DefaultValue(false), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override bool AutoSize
        {
            get
            {
                return base.AutoSize;
            }
            set
            {
                if (this.AutoSize != value)
                {
                    base.AutoSize = value;
                    AdjustSize();
                }
            }
        }
        protected Size CalcSize
        {
            get { return (_RatingItem.CalcSize); } 
        }
            
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        {
            if (this.AutoSize)
            {
                Size preferredSize = base.PreferredSize;
                width = preferredSize.Width;
                height = preferredSize.Height;
            }
            base.SetBoundsCore(x, y, width, height, specified);
        }
        private void AdjustSize()
        {
            if (this.AutoSize)
            {
                this.Size = base.PreferredSize;
            }
        }
        protected override void OnVisualPropertyChanged()
        {
            base.OnVisualPropertyChanged();
            this.AdjustSize();
        }
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            this.AdjustSize();
        }
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            if (this.AutoSize)
                this.AdjustSize();
        }
#endif
        #endregion
        #region ICommandSource Members
        protected virtual void ExecuteCommand()
        {
            if (_Command == null) return;
            CommandManager.ExecuteCommand(this);
        }
        /// 
        /// Gets or sets the command assigned to the item. Default value is null.
        /// Note that if this property is set to null Enabled property will be set to false automatically to disable the item.
        /// 
        [DefaultValue(null), Category("Commands"), Description("Indicates the command assigned to the item.")]
        public Command Command
        {
            get { return (Command)((ICommandSource)this).Command; }
            set
            {
                ((ICommandSource)this).Command = value;
            }
        }
        private ICommand _Command = null;
        //[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        ICommand ICommandSource.Command
        {
            get
            {
                return _Command;
            }
            set
            {
                bool changed = false;
                if (_Command != value)
                    changed = true;
                if (_Command != null)
                    CommandManager.UnRegisterCommandSource(this, _Command);
                _Command = value;
                if (value != null)
                    CommandManager.RegisterCommand(this, value);
                if (changed)
                    OnCommandChanged();
            }
        }
        /// 
        /// Called when Command property value changes.
        /// 
        protected virtual void OnCommandChanged()
        {
        }
        private object _CommandParameter = null;
        /// 
        /// Gets or sets user defined data value that can be passed to the command when it is executed.
        /// 
        [Browsable(true), DefaultValue(null), Category("Commands"), Description("Indicates user defined data value that can be passed to the command when it is executed."), System.ComponentModel.TypeConverter(typeof(System.ComponentModel.StringConverter)), System.ComponentModel.Localizable(true)]
        public object CommandParameter
        {
            get
            {
                return _CommandParameter;
            }
            set
            {
                _CommandParameter = value;
            }
        }
        #endregion
    }
}