using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
    [TypeConverter(typeof(SymbolDefConvertor))]
    [Editor(typeof(SymbolDefEditor), typeof(UITypeEditor))]
    public class SymbolDef : INotifyPropertyChanged, IDisposable, IProcessSerialElement
    {
        #region Private variables
        private string _Symbol = "";
        private string _SymbolRealized;
        private float _SymbolSize = -1f;
        private Color _SymbolColor = Color.Empty;
        private eSymbolSet _SymbolSet = eSymbolSet.Awesome;
        private Font _SymbolFont;
        private Size _RealSymbolSize;
        #endregion
        #region Public properties
        #region Symbol
        /// 
        /// Indicates the displayed Symbol. Symbol setting takes precedence over Image setting.
        /// 
        [DefaultValue(""), Category("Appearance"), Description("displayed Symbol. Symbol setting takes precedence over Image setting.")]
        [Editor("DevComponents.DotNetBar.Design.SymbolTypeEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))]
        public string Symbol
        {
            get { return (_Symbol); }
            set
            {
                if (value == null)
                    value = "";
                if (value != _Symbol)
                {
                    _Symbol = value;
                    _SymbolRealized = null;
                    OnPropertyChangedEx("Symbol");
                }
            }
        }
        #endregion
        #region SymbolColor
        /// 
        /// Gets or sets the color of the Symbol.
        /// 
        [Category("Appearance"), Description("Indicates color of the Symbol.")]
        public Color SymbolColor
        {
            get { return (_SymbolColor); }
            set
            {
                if (_SymbolColor != value)
                {
                    _SymbolColor = value;
                    OnPropertyChangedEx("SymbolColor", VisualChangeType.Render);
                }
            }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        private bool ShouldSerializeSymbolColor()
        {
            return (_SymbolColor.IsEmpty == false);
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        private void ResetSymbolColor()
        {
            SymbolColor = Color.Empty;
        }
        #endregion
        #region SymbolRealized
        /// 
        /// Gets the realized symbol string.
        /// 
        [Browsable(false)]
        public string SymbolRealized
        {
            get
            {
                if (_SymbolRealized == null)
                {
                    if (_Symbol != null)
                        _SymbolRealized = Symbols.GetSymbol(_Symbol);
                }
                return (_SymbolRealized);
            }
        }
        #endregion
        #region SymbolSet
        /// 
        /// Gets or sets the symbol set used to represent the Symbol.
        /// 
        [DefaultValue(eSymbolSet.Awesome)]
        public eSymbolSet SymbolSet
        {
            get { return (_SymbolSet); }
            set
            {
                if (_SymbolSet != value)
                {
                    _SymbolSet = value;
                    _SymbolRealized = null;
                    _SymbolFont = null;
                    _RealSymbolSize = Size.Empty;
                    OnPropertyChangedEx("SymbolSet");
                }
            }
        }
        #endregion
        #region SymbolSize
        /// 
        /// Indicates the size of the symbol in points.
        /// 
        [DefaultValue(-1f), Category("Appearance")]
        [Description("Indicates the size of the symbol in points.")]
        public float SymbolSize
        {
            get { return (_SymbolSize); }
            set
            {
                if (value != _SymbolSize)
                {
                    _SymbolSize = value;
                    _SymbolFont = null;
                    _RealSymbolSize = Size.Empty;
                    OnPropertyChangedEx("SymbolSize");
                }
            }
        }
        #endregion
        #region IsEmpty
        /// 
        /// Gets whether SymbolDef is Empty.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsEmpty
        {
            get
            {
                return ((string.IsNullOrEmpty(_Symbol) == true) &&
                    (_SymbolColor.IsEmpty == true) &&
                    (_SymbolSize == -1f));
            }
        }
        #endregion
        #endregion
        #region Internal properties
        #region SymbolFont
        internal Font SymbolFont
        {
            get
            {
                if (_SymbolFont == null)
                    _SymbolFont = Symbols.GetFont(SymbolSize, SymbolSet);
                return (_SymbolFont);
            }
            set
            {
                _SymbolFont = value;
            }
        }
        #endregion
        #region IsValidSymbol
        internal bool IsValidSymbol
        {
            get { return (string.IsNullOrEmpty(SymbolRealized) == false); }
        }
        #endregion
        #endregion
        #region GetSymbolSize
        internal Size GetSymbolSize(Graphics g)
        {
            if (_RealSymbolSize == Size.Empty)
            {
                Font font = SymbolFont;
                Size size = g.MeasureString(SymbolRealized, font).ToSize();
                size.Width++;
                size.Height++;
                _RealSymbolSize = size;
            }
            return (_RealSymbolSize);
        }
        #endregion
        #region Copy
        /// 
        /// Creates an exact copy of the SymbolDef.
        /// 
        /// Copy of the SymbolDef.
        public SymbolDef Copy()
        {
            SymbolDef style = new SymbolDef();
            CopyTo(style);
            return (style);
        }
        #endregion
        #region CopyTo
        /// 
        /// Returns the copy of the style.
        /// 
        /// Copy of the style.
        public void CopyTo(SymbolDef style)
        {
            style.Symbol = _Symbol;
            style.SymbolColor = _SymbolColor;
            style.SymbolSet = _SymbolSet;
            style.SymbolSize = _SymbolSize;
        }
        #endregion
        #region GetSerialData
        internal SerialElementCollection GetSerialData(string serialName)
        {
            if (IsEmpty == false)
            {
                SerialElementCollection sec = new SerialElementCollection();
                if (serialName != null)
                {
                    if (serialName.Equals("") == true)
                        serialName = "SymbolDef";
                    sec.AddStartElement(serialName);
                }
                if (IsValidSymbol == true)
                    sec.AddValue("Symbol", Symbol);
                sec.AddValue("SymbolColor", SymbolColor, Color.Empty);
                sec.AddValue("SymbolSet", SymbolSet, eSymbolSet.Awesome);
                sec.AddValue("SymbolSize", SymbolSize, -1f);
                if (serialName != null)
                    sec.AddEndElement(serialName);
                return (sec);
            }
            return (null);
        }
        #endregion
        #region PutSerialData
        #region ProcessValue
        void IProcessSerialElement.ProcessValue(SerialElement se)
        {
            switch (se.Name)
            {
                case "Symbol":
                    Symbol = se.GetValueString();
                    break;
                case "SymbolColor":
                    SymbolColor = se.GetValueColor();
                    break;
                case "SymbolSet":
                    SymbolSet = (eSymbolSet)se.GetValueEnum(typeof(eSymbolSet));
                    break;
                case "SymbolSize":
                    SymbolSize = float.Parse(se.StringValue);
                    break;
                default:
                    throw new Exception("Unknown Serial Value (" + se.Name + ")");
            }
        }
        #endregion
        #region ProcessCollection
        void IProcessSerialElement.ProcessCollection(SerialElement se)
        {
            switch (se.Name)
            {
                default:
                    throw new Exception("Unknown Serial Collection (" + se.Name + ")");
            }
        }
        #endregion
        #endregion
        #region INotifyPropertyChanged Members
        /// 
        /// Occurs when property value has changed.
        /// 
        public event PropertyChangedEventHandler PropertyChanged;
        /// 
        /// Raises the PropertyChanged event.
        /// 
        /// Event arguments
        protected virtual void OnPropertyChanged(VisualPropertyChangedEventArgs e)
        {
            PropertyChangedEventHandler eh = PropertyChanged;
            if (eh != null)
                eh(this, e);
        }
        /// 
        /// Raises the PropertyChanged event.
        /// 
        /// Event arguments
        protected virtual void OnPropertyChangedEx(string s)
        {
            PropertyChangedEventHandler eh = PropertyChanged;
            if (eh != null)
            {
                VisualPropertyChangedEventArgs e =
                    new VisualPropertyChangedEventArgs(s);
                eh(this, e);
            }
        }
        /// 
        /// Raises the PropertyChanged event.
        /// 
        /// Event arguments
        protected virtual void OnPropertyChangedEx(string s, VisualChangeType changeType)
        {
            PropertyChangedEventHandler eh = PropertyChanged;
            if (eh != null)
            {
                VisualPropertyChangedEventArgs e =
                    new VisualPropertyChangedEventArgs(s, changeType);
                eh(this, e);
            }
        }
        #endregion
        #region UpdateChangeHandler
        private void UpdateChangeHandler(
            INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
        {
            if (oldValue != null)
                oldValue.PropertyChanged -= StyleChanged;
            if (newValue != null)
                newValue.PropertyChanged += StyleChanged;
        }
        #endregion
        #region StyleChanged
        /// 
        /// StyleChanged
        /// 
        /// 
        /// 
        protected virtual void StyleChanged(
            object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChanged((VisualPropertyChangedEventArgs)e);
        }
        #endregion
        #region IDisposable
        /// 
        /// Dispose
        /// 
        public void Dispose()
        {
            SymbolFont = null;
        }
 
        #endregion
    }
    #region SymbolDefConvertor
    ///
    /// SymbolDefConvertor
    ///
    public class SymbolDefConvertor : ExpandableObjectConverter
    {
        /// 
        /// ConvertTo
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public override object ConvertTo(
            ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                SymbolDef sd = value as SymbolDef;
                if (sd != null)
                    return (sd.SymbolSet.ToString());
            }
            return (base.ConvertTo(context, culture, value, destinationType));
        }
    }
    #endregion
    #region SymbolDefEditor
    ///
    /// SymbolDefEditor
    ///
    public class SymbolDefEditor : UITypeEditor
    {
        #region GetPaintValueSupported
        /// 
        /// GetPaintValueSupported
        /// 
        /// 
        /// 
        public override bool GetPaintValueSupported(ITypeDescriptorContext context)
        {
            return (true);
        }
        #endregion
        #region PaintValue
        /// 
        /// PaintValue
        /// 
        /// 
        public override void PaintValue(PaintValueEventArgs e)
        {
            SymbolDef sd = e.Value as SymbolDef;
            if (sd != null)
            {
                Font font = Symbols.GetFont(10, sd.SymbolSet);
                Color color = sd.SymbolColor;
                if (sd.SymbolColor.IsEmpty || sd.SymbolColor == Color.White)
                    color = Color.Brown;
                using (Brush br = new SolidBrush(color))
                {
                    using (StringFormat sf = new StringFormat())
                    {
                        sf.Alignment = StringAlignment.Center;
                        sf.LineAlignment = StringAlignment.Center;
                        e.Graphics.DrawString(sd.SymbolRealized, font, br, e.Bounds, sf);
                    }
                }
            }
        }
        #endregion
    }
    #endregion
}