using System;
using System.Collections.Generic;
using System.Drawing;
using DevComponents.DotNetBar.Charts.Style;
namespace DevComponents.DotNetBar.Charts
{
    /// 
    /// Provides helpers when working with EffectiveStyles.
    /// 
    public class EffectiveStyles where T : BaseVisualStyle, new()
    {
        #region Private variables
        private IEffectiveStyle _ChartElement;
        private VisualStyles _Styles = new VisualStyles();
        private ushort[] _StyleUpdateCount;
        private ushort[] _GlobalStyleUpdateCount;
        private List[] _StyleList;
        #endregion
        public EffectiveStyles(IEffectiveStyle chartElement)
        {
            _ChartElement = chartElement;
            int len = Enum.GetValues(typeof(StyleType)).Length - 1;
            _StyleUpdateCount = new ushort[len];
            _GlobalStyleUpdateCount = new ushort[len];
            _StyleList = new List[len];
            for (int i = 0; i < len; i++)
            {
                _StyleUpdateCount[i] = ushort.MaxValue;
                _GlobalStyleUpdateCount[i] = ushort.MaxValue;
            }
        }
        #region Public properties
        #region StyleType Indexer
        public T this[StyleType type]
        {
            get { return (GetEffectiveStyle(type)); }
        }
        #endregion
        #region StyleState Indexer
        public T this[StyleState state]
        {
            get { return (GetEffectiveStyle(state)); }
        }
        #endregion
        #endregion
        #region GetEffectiveStyle
        internal T GetEffectiveStyle(StyleType type)
        {
            return (GetStyle(type));
        }
        internal T GetEffectiveStyle(StyleState state)
        {
            if (_ChartElement.ChartControl.DesignerHosted == true)
                state &= ~(StyleState.MouseOver | StyleState.Selected);
            switch (state)
            {
                case StyleState.MouseOver:
                    return (GetStyle(StyleType.MouseOver));
                case StyleState.Selected:
                    return (GetStyle(StyleType.Selected));
                case StyleState.Selected | StyleState.MouseOver:
                    return (GetStyle(StyleType.SelectedMouseOver));
                default:
                    return (GetStyle(StyleType.Default));
            }
        }
        #endregion
        #region GetStyle
        internal T GetStyle(StyleType e)
        {
            VisualStyles cvs = _Styles;
            if (cvs == null)
                cvs = new VisualStyles();
            int styleIndex = cvs.StyleIndex(e);
            ushort styleUpdateCount = _StyleUpdateCount[styleIndex];
            ushort globalUpdateCount = _ChartElement.ChartControl.GlobalUpdateCount;
            T style = cvs.Style(e);
            if (_GlobalStyleUpdateCount[styleIndex] != globalUpdateCount)
            {
                if (style != null)
                    styleUpdateCount = GetStyleUpdateCount(styleIndex);
            }
            if (style == null || _StyleUpdateCount[styleIndex] != styleUpdateCount)
            {
                style = new T();
                if (_StyleList[styleIndex] == null)
                    _StyleList[styleIndex] = new List();
                _StyleList[styleIndex].Clear();
                style.StyleType = e;
                style.StyleList = _StyleList[styleIndex];
                style.StyleUpdateMode = StyleUpdateMode.UpdateCount;
                StyleType[] css = style.GetApplyStyleTypes(e);
                if (css != null)
                {
                    foreach (StyleType cs in css)
                        _ChartElement.ApplyStyles(style, cs);
                }
                style.StyleUpdateMode = StyleUpdateMode.None;
                _ChartElement.ApplyDefaults(style, e);
                style.StyleUpdateMode = (StyleUpdateMode.UpdateCount | StyleUpdateMode.Notify);
                BaseVisualStyle vstyle = (BaseVisualStyle)style;
                _ChartElement.GetElementStyle(_ChartElement, e, ref vstyle);
                _StyleUpdateCount[styleIndex] = GetStyleUpdateCount(styleIndex);
                style.StyleList = null;
                cvs[e] = style;
                _Styles = cvs;
            }
            _GlobalStyleUpdateCount[styleIndex] = globalUpdateCount;
            return (cvs[e]);
        }
        #region GetStyleUpdateCount
        private ushort GetStyleUpdateCount(int styleIndex)
        {
            ushort styleCount = 0;
            List slist = _StyleList[styleIndex];
            if (slist != null)
            {
                foreach (BaseVisualStyle style in slist)
                    styleCount += style.StyleUpdateCount;
            }
            return (styleCount);
        }
        #endregion
        #endregion
        #region InvalidateStyle
        public bool InvalidateStyle(StyleType type)
        {
            if (_Styles != null)
            {
                if (_Styles[type] != null)
                {
                    _Styles[type].Dispose();
                    _Styles[type] = null;
                    return (true);
                }
            }
            return (false);
        }
        #endregion
        #region InvalidateStyles
        public void InvalidateStyles()
        {
            if (_Styles != null)
            {
                _Styles.Dispose();
                _Styles = null;
            }
        }
        #endregion
    }
    /// 
    /// Provides helpers when working with EffectiveStyle.
    /// 
    public class EffectiveStyle where T : BaseVisualStyle, new()
    {
        #region Private variables
        private IEffectiveStyle _ChartElement;
        private T _Style;
        private ushort _StyleUpdateCount = ushort.MaxValue;
        private ushort _GlobalStyleUpdateCount = ushort.MaxValue;
        private List _StyleList = new List();
        #endregion
        public EffectiveStyle(IEffectiveStyle chartElement)
        {
            _ChartElement = chartElement;
        }
        #region Style
        internal T Style
        {
            get
            {
                ushort styleUpdateCount = _StyleUpdateCount;
                ushort globalUpdateCount = _ChartElement.ChartControl.GlobalUpdateCount;
                if (_GlobalStyleUpdateCount != globalUpdateCount)
                {
                    if (_Style != null)
                        styleUpdateCount = GetStyleUpdateCount();
                }
                if (_Style == null || _StyleUpdateCount != styleUpdateCount)
                {
                    T style = new T();
                    _StyleList.Clear();
                    style.StyleList = _StyleList;
                    style.StyleType = StyleType.Default;
                    _ChartElement.ApplyStyles(style);
                    _ChartElement.ApplyDefaults(style, StyleType.Default);
                    BaseVisualStyle vstyle = (BaseVisualStyle)style;
                    _ChartElement.GetElementStyle(_ChartElement, StyleType.Default, ref vstyle);
                    _StyleUpdateCount = GetStyleUpdateCount();
                    style.StyleList = null;
                    _Style = style;
                }
                _GlobalStyleUpdateCount = globalUpdateCount;
                return (_Style);
            }
        }
        #region GetStyleUpdateCount
        private ushort GetStyleUpdateCount()
        {
            ushort styleCount = 0;
            List slist = _StyleList;
            if (slist != null)
            {
                foreach (BaseVisualStyle style in slist)
                    styleCount += style.StyleUpdateCount;
            }
            return (styleCount);
        }
        #endregion
        #endregion
        #region InvalidateStyle
        public bool InvalidateStyle()
        {
            if (_Style != null)
            {
                _Style.Dispose();
                _Style = null;
                return (true);
            }
            return (false);
        }
        #endregion
    }
    #region IEffectiveStyle
    public interface IEffectiveStyle
    {
        void ApplyStyles(BaseVisualStyle style);
        void ApplyStyles(BaseVisualStyle style, StyleType styleType);
        void ApplyDefaults(BaseVisualStyle style, StyleType styleType);
        void GetElementStyle(IEffectiveStyle chartElement, StyleType styleType, ref BaseVisualStyle style);
        ChartControl ChartControl
        {
            get;
        }
    }
    #endregion
}