using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Collections;
using System.Windows.Forms;
using System.Reflection;
using System.Globalization;
using DevComponents.DotNetBar.Primitives;
namespace DevComponents.DotNetBar
{
    /// 
    /// Provides binding support for ItemPanel control.
    /// 
    public class ItemVisualGenerator
    {
        #region Constructor
        private IBindingSupport _Parent = null;
        /// 
        /// Initializes a new instance of the ItemVisualGenerator class.
        /// 
        /// 
        public ItemVisualGenerator(IBindingSupport parent)
        {
            _Parent = parent;
        }
        #endregion
        #region Implementation
        private object _DataSource = null;
        /// 
        /// Gets or sets the data source for the ComboTree. Expected is an object that implements the IList or IListSource interfaces, 
        /// such as a DataSet or an Array. The default is null.
        /// 
        [AttributeProvider(typeof(IListSource)), Description("Indicates data source for the ComboTree."), Category("Data"), DefaultValue(null), RefreshProperties(RefreshProperties.Repaint)]
        public object DataSource
        {
            get
            {
                return _DataSource;
            }
            set
            {
                if (((value != null) && !(value is IList)) && !(value is IListSource))
                {
                    throw new ArgumentException("Data type is not supported for complex data binding");
                }
                if (_DataSource != value)
                {
                    if (DesignMode)
                        _DataSource = value;
                    else
                        this.SetDataConnection(value, true);
                }
            }
        }
        private bool DesignMode
        {
            get
            {
                if (_Parent is IComponent && ((IComponent)_Parent).Site != null)
                    return ((IComponent)_Parent).Site.DesignMode;
                if (_Parent is Control && ((Control)_Parent).Site != null)
                    return ((Control)_Parent).Site.DesignMode;
                return false;
            }
        }
        private bool _InSetDataConnection = false;
        private void SetDataConnection(object newDataSource, bool force)
        {
            bool dataSourceChanged = _DataSource != newDataSource;
            if (!_InSetDataConnection)
            {
                try
                {
                    if (force || dataSourceChanged)
                    {
                        _InSetDataConnection = true;
                        IList list = (this.DataManager != null) ? this.DataManager.List : null;
                        bool isDataManagerNull = this.DataManager == null;
                        this.UnwireDataSource();
                        _DataSource = newDataSource;
                        this.WireDataSource();
                        if (_IsDataSourceInitialized && !IsCustomCollection)
                        {
                            CurrencyManager manager = null;
                            if (((newDataSource != null) && (_Parent.BindingContext != null)) && (newDataSource != Convert.DBNull))
                            {
                                string bindingPath = "";
                                if (_Bindings != null && _Bindings.Count > 0)
                                    bindingPath = _Bindings[0].BindingMemberInfo.BindingPath;
                                manager = (CurrencyManager)_Parent.BindingContext[newDataSource, bindingPath];
                            }
                            if (_DataManager != manager)
                            {
                                if (_DataManager != null)
                                {
                                    _DataManager.ItemChanged -= new ItemChangedEventHandler(this.DataManager_ItemChanged);
                                    _DataManager.PositionChanged -= new EventHandler(this.DataManager_PositionChanged);
                                }
                                _DataManager = manager;
                                if (_DataManager != null)
                                {
                                    _DataManager.ItemChanged += new ItemChangedEventHandler(this.DataManager_ItemChanged);
                                    _DataManager.PositionChanged += new EventHandler(this.DataManager_PositionChanged);
                                }
                            }
                            if (((_DataManager != null) && (dataSourceChanged)) && !ValidateDisplayMembers(_Bindings))
                            {
                                throw new ArgumentException("Wrong Bindings parameter", "newBindings");
                            }
                            if ((_DataManager != null && (dataSourceChanged || force))
                                && (dataSourceChanged || (force && ((list != _DataManager.List) || isDataManagerNull))))
                            {
                                DataManager_ItemChanged(_DataManager, null);
                            }
                        }
                        _Converters.Clear();
                    }
                }
                finally
                {
                    _InSetDataConnection = false;
                }
            }
        }
        private bool ValidateDisplayMembers(List members)
        {
            if (members == null || members.Count == 0) return true;
            foreach (BindingDef item in members)
            {
                if (item.BindingMemberInfo != null && !BindingMemberInfoInDataManager(item.BindingMemberInfo))
                    return false;
            }
            return true;
        }
        private bool BindingMemberInfoInDataManager(BindingMemberInfo bindingMemberInfo)
        {
            if (_DataManager != null)
            {
                PropertyDescriptorCollection itemProperties = _DataManager.GetItemProperties();
                int count = itemProperties.Count;
                for (int i = 0; i < count; i++)
                {
                    if (!typeof(IList).IsAssignableFrom(itemProperties[i].PropertyType) && itemProperties[i].Name.Equals(bindingMemberInfo.BindingField))
                    {
                        return true;
                    }
                }
                for (int j = 0; j < count; j++)
                {
                    if (!typeof(IList).IsAssignableFrom(itemProperties[j].PropertyType) && (string.Compare(itemProperties[j].Name, bindingMemberInfo.BindingField, true, CultureInfo.CurrentCulture) == 0))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        private List _Bindings = new List();
        public List Bindings
        {
            get { return _Bindings; }
            set
            {
                if (value != _Bindings)
                {
                    List oldValue = _Bindings;
                    _Bindings = value;
                    OnBindingsChanged(oldValue, value);
                }
            }
        }
        /// 
        /// Called when Bindings property has changed.
        /// 
        /// Old property value
        /// New property value
        protected virtual void OnBindingsChanged(List oldValue, List newValue)
        {
            //OnPropertyChanged(new PropertyChangedEventArgs("Bindings"));
        }
        private CurrencyManager _DataManager = null;
        internal CurrencyManager DataManager
        {
            get
            {
                return _DataManager;
            }
        }
        private bool _IsDataSourceInitEventHooked = false;
        private void UnwireDataSource()
        {
            if (IsCustomCollection)
            {
                CustomCollection