using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
    /// 
    /// Represents a PointLabel group.
    /// 
    public class PointLabelGroup
    {
        #region Private data
        private ChartSeries _ChartSeries;
        private List _PointLabels;
        #endregion
        public PointLabelGroup(ChartSeries chartSeries, List pointLabels)
        {
            _ChartSeries = chartSeries;
            _PointLabels = pointLabels;
        }
        #region Public properties
        #region ChartSeries
        /// 
        /// Gets or sets the associated chart series.
        /// 
        public ChartSeries ChartSeries
        {
            get { return (_ChartSeries); }
            set { _ChartSeries = value; }
        }
        #endregion
        #region PointLabels
        /// 
        /// Gets or sets the associated list of PointLabels.
        /// 
        public List PointLabels
        {
            get { return (_PointLabels); }
            set { _PointLabels = value; }
        }
        #endregion
        #endregion
    }
    /// 
    /// Represents a PointLabel (label associated with a data point in the chart).
    /// 
    public class PointLabel : IDisposable
    {
        #region Private data
        private SeriesPoint _SeriesPoint;
        private float _Angle;
        private Rectangle _Bounds;
        private Point _EdgePoint;
        private Point _Point;
        private string _Label;
        private Size _LabelSize;
        private BarLabelPosition _BarLabelPosition = BarLabelPosition.NotSet;
        private DataLabelVisualStyle _DataLabelVisualStyle;
        private States _States;
        #endregion
        public PointLabel(SeriesPoint sp, Point pt, string label)
        {
            _SeriesPoint = sp;
            _Point = pt;
            _Label = label;
            InitDefaultStates();
        }
        #region InitDefaultStates
        private void InitDefaultStates()
        {
            SetState(States.Visible, true);
            SetState(States.NeedsMeasured, true);
        }
        #endregion
        #region Public properties
        #region Angle
        /// 
        /// Gets the angle used to display the point label 
        /// associated with the data point.
        /// 
        public float Angle
        {
            get { return (_Angle); }
            internal set { _Angle = value; }
        }
        #endregion
        #region BarLabelPosition
        /// 
        /// Gets or sets the position of bar series labels.
        /// 
        [Description("Indicates the position of bar series labels.")]
        public BarLabelPosition BarLabelPosition
        {
            get { return (_BarLabelPosition); }
            set { _BarLabelPosition = value; }
        }
        #endregion
        #region DataLabelVisualStyle
        /// 
        /// Gets or sets the visual style for the data label.
        /// 
        public DataLabelVisualStyle DataLabelVisualStyle
        {
            get { return (_DataLabelVisualStyle); }
            set
            {
                if (value != _DataLabelVisualStyle)
                {
                    DataLabelVisualStyle oldValue = _DataLabelVisualStyle;
                    _DataLabelVisualStyle = value;
                    StyleVisualChangeHandler(oldValue, value);
                }
            }
        }
        #endregion
        #region FixedSize
        /// 
        /// Gets or set whether the LabelSize is a fixed size.
        /// 
        public bool IsFixedSize
        {
            get { return (TestState(States.IsFixedSize)); }
            set { SetState(States.IsFixedSize, value); }
        }
        #endregion
        #region Label
        /// 
        /// Gets or sets the label text
        /// 
        public string Label
        {
            get { return (_Label); }
            set
            {
                NeedsMeasured = true;
                _Label = value;
            }
        }
        #endregion
        #region LabelSize
        /// 
        /// Gets or sets the label size.
        /// 
        public Size LabelSize
        {
            get { return (_LabelSize); }
            set
            {
                _LabelSize = value;
                NeedsMeasured = false;
            }
        }
        #endregion
        #region SeriesPoint
        /// 
        /// Gets the associated SeriesPoint.
        /// 
        public SeriesPoint SeriesPoint
        {
            get { return (_SeriesPoint); }
            internal set { _SeriesPoint = value; }
        }
        #endregion
        #region Visible
        /// 
        /// Gets or sets whether the label is visible.
        /// 
        public bool Visible
        {
            get { return (TestState(States.Visible)); }
            set { SetState(States.Visible, value); }
        }
        #endregion
        #endregion
        #region Internal properties
        #region Bounds
        internal Rectangle Bounds
        {
            get { return (_Bounds); }
            set { _Bounds = value; }
        }
        #endregion
        #region EdgePoint
        internal Point EdgePoint
        {
            get { return (_EdgePoint); }
            set { _EdgePoint = value; }
        }
        #endregion
        #region IsDataLabel
        internal bool IsDataLabel
        {
            get { return (TestState(States.IsDataLabel)); }
            set { SetState(States.IsDataLabel, value); }
        }
        #endregion
        #region NeedsMeasured
        internal bool NeedsMeasured
        {
            get { return (TestState(States.NeedsMeasured)); }
            set { SetState(States.NeedsMeasured, value); }
        }
        #endregion
        #region Point
        internal Point Point
        {
            get { return (_Point); }
            set { _Point = value; }
        }
        #endregion
        #endregion
        #region States
        [Flags]
        private enum States : uint
        {
            IsFixedSize = (1U << 0),
            NeedsMeasured = (1U << 1),
            Visible = (1U << 2),
            IsDataLabel = (1U << 3),
        }
        #region TestState
        private bool TestState(States state)
        {
            return ((_States & state) == state);
        }
        #endregion
        #region SetState
        private void SetState(States state, bool value)
        {
            if (value == true)
                _States |= state;
            else
                _States &= ~state;
        }
        #endregion
        #endregion
        #region StyleVisualChangeHandler
        private void StyleVisualChangeHandler(
            INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
        {
            if (oldValue != null)
                oldValue.PropertyChanged -= StyleChanged;
            if (newValue != null)
                newValue.PropertyChanged += StyleChanged;
        }
        private void StyleChanged(object sender, PropertyChangedEventArgs e)
        {
            NeedsMeasured = true;
        }
        #endregion
        #region IDisposable
        public void Dispose()
        {
            DataLabelVisualStyle = null;
        }
        #endregion
    }
}