using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace HwComWrapperNETGui
{
    /// <summary>
    /// Helper class to directly open the property grid collection editor.
    /// </summary>
    class CollectionEditorHelper : IWindowsFormsEditorService, ITypeDescriptorContext
    {
        private readonly IWin32Window owner;
        private readonly object component;
        private readonly PropertyDescriptor property;
        private DialogResult dialogResult = DialogResult.Cancel;

        /// <summary>
        /// Opens the property grid collection editor to modify the given property.
        /// </summary>
        /// <param name="owner">The parent form.</param>
        /// <param name="component">The object which should be modified.</param>
        /// <param name="propertyName">The name of the property which should be modified.</param>
        /// <returns><see cref="DialogResult.Cancel"/>if user  has canceled the collection editor. Otherwise <see cref="DialogResult.OK"/> </returns>
        public static DialogResult EditValue(IWin32Window owner, object component, string propertyName)
        {
            var prop = TypeDescriptor.GetProperties(component)[propertyName];
            if (prop == null)
            {
                throw new ArgumentException("propertyName");
            }

            UITypeEditor editor = (UITypeEditor)prop.GetEditor(typeof(UITypeEditor));
            CollectionEditorHelper collectionEditorHelper = new CollectionEditorHelper(owner, component, prop);
            if (editor != null && editor.GetEditStyle(collectionEditorHelper) == UITypeEditorEditStyle.Modal)
            {
                var value = prop.GetValue(component);
                value = editor.EditValue(collectionEditorHelper, collectionEditorHelper, value);
                if (!prop.IsReadOnly)
                {
                    prop.SetValue(component, value);
                }
            }

            return collectionEditorHelper.dialogResult;
        }
      
        private CollectionEditorHelper(IWin32Window owner, object component, PropertyDescriptor property)
        {
            this.owner = owner;
            this.component = component;
            this.property = property;
        }

        #region IWindowsFormsEditorService Members

        public void CloseDropDown()
        {
            throw new NotImplementedException();
        }

        public void DropDownControl(System.Windows.Forms.Control control)
        {
            throw new NotImplementedException();
        }

        public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.Form dialog)
        {
            dialog.CancelButton = null;
            dialogResult = dialog.ShowDialog(owner);
            return dialogResult;
        }

        #endregion

        #region IServiceProvider Members

        public object GetService(Type serviceType)
        {
            if (serviceType == typeof(IWindowsFormsEditorService))
            {
                return this;
            }

            return null;
        }

        #endregion

        #region ITypeDescriptorContext Members

        IContainer ITypeDescriptorContext.Container
        {
            get { return null; }
        }

        object ITypeDescriptorContext.Instance
        {
            get { return component; }
        }

        void ITypeDescriptorContext.OnComponentChanged()
        { }

        bool ITypeDescriptorContext.OnComponentChanging()
        {
            return true;
        }

        PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
        {
            get { return property; }
        }

        #endregion
    }
}
