using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using DevComponents.DotNetBar.Controls;
namespace DevComponents.DotNetBar.Design
{
    public class ToolboxControlDesigner : ControlDesigner
    {
        public void SelectionRefresh()
        {
            Message m = new Message();
            m.Msg = 0x115;
            base.WndProc(ref m);
        }
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            IDesignerHost dh = this.GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (dh != null)
                dh.LoadComplete += new EventHandler(dh_LoadComplete);
            // If our item is removed we need to clean-up
            IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
            if (cc != null)
            {
                cc.ComponentRemoved += ComponentRemoved;
                cc.ComponentRemoving += ComponentRemoving;
            }
        }
        private bool _InternalRemoving = false;
        private void ComponentRemoving(object sender, ComponentEventArgs e)
        {
            if (e.Component != this.Component) return;
            if (!_InternalRemoving)
            {
                _InternalRemoving = true;
                try
                {
                    // Unhook events
                    IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
                    if (cc != null)
                        cc.ComponentRemoving -= ComponentRemoving;
                    ToolboxControl tc = (ToolboxControl) this.Component;
                    IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost));
                    if (dh == null || tc == null)
                        return;
                    for (int i = tc.Groups.Count - 1; i >= 0; i--)
                    {
                        BaseItem item = tc.Groups[i];
                        // Covers the undo case in designer
                        if (item.Parent == tc.ItemsPanel.GetBaseItemContainer())
                        {
                            DestroySubItems(item, dh);
                            dh.DestroyComponent(item);
                        }
                    }
                }
                finally
                {
                    _InternalRemoving = false;
                }
            }
        }
        protected virtual void DestroySubItems(BaseItem parent, IDesignerHost dh)
        {
            if (parent is ControlContainerItem)
            {
                if (((ControlContainerItem)parent).Control != null)
                {
                    Control c = ((ControlContainerItem)parent).Control;
                    ((ControlContainerItem)parent).Control = null;
                    dh.DestroyComponent(c);
                }
            }
            else if (parent is DockContainerItem)
            {
                if (((DockContainerItem)parent).Control != null)
                {
                    Control c = ((DockContainerItem)parent).Control;
                    ((DockContainerItem)parent).Control = null;
                    dh.DestroyComponent(c);
                }
            }
            BaseItem[] subitems = new BaseItem[parent.SubItems.Count];
            parent.SubItems.CopyTo(subitems, 0);
            foreach (BaseItem item in subitems)
            {
                DestroySubItems(item, dh);
                dh.DestroyComponent(item);
            }
        }
        protected virtual void DestroySubItems(BaseItem parent)
        {
            IDesignerHost dh = GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (dh != null)
                DestroySubItems(parent, dh);
        }
        private void ComponentRemoved(object sender, ComponentEventArgs e)
        {
            ToolboxGroup group = e.Component as ToolboxGroup;
            ToolboxControl tc = (ToolboxControl)this.Control;
            if (group != null && tc != null)
            {
                if (tc.Groups.Contains(group))
                {
                    IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
                    if (cc != null)
                        cc.OnComponentChanging(tc, TypeDescriptor.GetProperties(tc)["Groups"]);
                    tc.Groups.Remove(group);
                    if (cc != null)
                        cc.OnComponentChanged(tc, TypeDescriptor.GetProperties(tc)["Groups"], null, null);
                }
                this.RecalcLayout();
            }
        }
        public override System.Collections.ICollection AssociatedComponents
        {
            get
            {
                ArrayList c = new ArrayList(base.AssociatedComponents);
                ToolboxControl tc = (ToolboxControl) this.Control;
                if (tc != null)
                {
                    foreach (BaseItem item in tc.Groups)
                    {
                        if (item.DesignMode)
                            c.Add(item);
                    }
                }
                return c;
            }
        }
        private void RecalcLayout()
        {
            ToolboxControl tc = (ToolboxControl)this.Control;
            if (tc == null) return;
            tc.RecalcLayout();
        }
        public override void InitializeNewComponent(IDictionary defaultValues)
        {
            SetDefaults();
            base.InitializeNewComponent(defaultValues);
        }
        private void SetDefaults()
        {
            ToolboxGroup group = CreateToolboxGroup(true);
            CreateToolboxItem(group, true);
            IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (dh == null)
                return;
            this.Control.Size = new Size(200, 200);
#if !TRIAL
            string key = GetLicenseKey();
            ToolboxControl tc = this.Control as ToolboxControl;
            tc.LicenseKey = key;
#endif
        }
        public void CreateGroup()
        {
            CreateToolboxGroup(true);
        }
        private ToolboxGroup CreateToolboxGroup(bool addToCollections)
        {
            ToolboxControl tc = this.Control as ToolboxControl;
            IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (dh == null)
                return null;
            ToolboxGroup toolboxGroup = null;
            IComponentChangeService change = this.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
            if (addToCollections)
            {
                if (change != null)
                {
                    change.OnComponentChanging(this.Component, TypeDescriptor.GetProperties(tc).Find("Groups", true));
                }
            }
            toolboxGroup = dh.CreateComponent(typeof(ToolboxGroup)) as ToolboxGroup;
            if (toolboxGroup != null)
            {
                toolboxGroup.TitleText = toolboxGroup.Name;
                toolboxGroup.Expanded = true;
                toolboxGroup.LayoutOrientation = eOrientation.Vertical;
                toolboxGroup.MultiLine = false;
                toolboxGroup.ResizeItemsToFit = true;
                if (addToCollections)
                {
                    tc.Groups.Add(toolboxGroup);
                    if (change != null)
                    {
                        change.OnComponentChanged(this.Component, TypeDescriptor.GetProperties(tc).Find("Groups", true), null, null);
                    }
                }
            }
            return toolboxGroup;
        }
        private ToolboxItem CreateToolboxItem(ToolboxGroup parentGroup, bool addToCollections)
        {
            ToolboxControl tc = this.Control as ToolboxControl;
            IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (dh == null)
                return null;
            if (parentGroup == null)
                throw new ArgumentNullException("parentGroup", "ToolboxGroup must be specified");
            ToolboxItem item = null;
            IComponentChangeService change = this.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
            if (addToCollections)
            {
                if (change != null)
                {
                    change.OnComponentChanging(this.Component, TypeDescriptor.GetProperties(parentGroup).Find("SubItems", true));
                }
            }
            item = dh.CreateComponent(typeof(ToolboxItem)) as ToolboxItem;
            if (item != null)
            {
                item.Text = item.Name;
                item.Symbol = "\ue251";
                item.SymbolSet = eSymbolSet.Material;
                if (addToCollections)
                {
                    parentGroup.SubItems.Add(item);
                    if (change != null)
                    {
                        change.OnComponentChanged(this.Component, TypeDescriptor.GetProperties(parentGroup).Find("Nodes", true), null, null);
                    }
                }
            }
            return item;
        }
        protected override bool GetHitTest(System.Drawing.Point point)
        {
            if (base.GetHitTest(point))
                return true;
            ToolboxControl c = this.Control as ToolboxControl;
            if (c == null) return false;
            Point pc = c.ItemsPanel.PointToClient(point);
            if (c.ItemsPanel.VScrollBar != null && c.ItemsPanel.VScrollBar.Visible && c.ItemsPanel.VScrollBar.Bounds.Contains(pc))
                return true;
            if (c.ItemsPanel.HScrollBar != null && c.ItemsPanel.HScrollBar.Visible && c.ItemsPanel.HScrollBar.Bounds.Contains(pc))
                return true;
            return base.GetHitTest(point);
        }
        private bool IsControlSelected
        {
            get
            {
                ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
                if (ss == null) return false;
                ICollection selected = ss.GetSelectedComponents();
                if (IsSelected(selected, this.Control))
                    return true;
                return false;
            }
        }
        private bool IsSelected(ICollection selectedComponents, object item)
        {
            foreach (object o in selectedComponents)
            {
                if (o == item) return true;
            }
            return false;
        }
        private System.Windows.Forms.Control _DesignerHost = null;
        /// 
        /// Selection support for items on container.
        /// 
        protected override void WndProc(ref Message m)
        {
            if (_DesignerHost == null)
                _DesignerHost = System.Windows.Forms.Control.FromHandle(m.HWnd);
            switch (m.Msg)
            {
                case WinApi.WM_LBUTTONDOWN:
                case WinApi.WM_RBUTTONDOWN:
                    {
                        if (OnMouseDown(ref m, m.Msg == WinApi.WM_LBUTTONDOWN ? MouseButtons.Left : MouseButtons.Right))
                            return;
                        break;
                    }
                case WinApi.WM_RBUTTONUP:
                case WinApi.WM_LBUTTONUP:
                    {
                        if (OnMouseUp(ref m, m.Msg == WinApi.WM_LBUTTONDOWN ? MouseButtons.Left : MouseButtons.Right))
                            return;
                        break;
                    }
            }
            base.WndProc(ref m);
        }
        protected virtual bool OnMouseUp(ref Message m, MouseButtons param1)
        {
            if (_MouseDownSelectionPerformed)
            {
                _MouseDownSelectionPerformed = false;
                return true;
            }
            return false;
        }
        private bool _MouseDownSelectionPerformed = false;
        protected virtual bool OnMouseDown(ref Message m, MouseButtons button)
        {
            ToolboxControl lc = this.Control as ToolboxControl;
            if (lc == null) return false;
            if (m.HWnd != lc.ItemsPanel.Handle)
                return false;
            Point p = new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam));
            BaseItem item = lc.ItemsPanel.HitTest(p);
            if (item != null)
            {
                SelectComponent(item, (Control.ModifierKeys == Keys.Control || Control.ModifierKeys == Keys.Shift) ? SelectionTypes.Add : SelectionTypes.Primary);
                _MouseDownSelectionPerformed = true;
                return true;
            }
            else if (!IsControlSelected)
            {
                SelectComponent(this.Control, SelectionTypes.Replace);
                //return true;
            }
            return false;
        }
        protected virtual void SelectComponent(IComponent comp, SelectionTypes selectionType)
        {
            ISelectionService selection = (ISelectionService)this.GetService(typeof(ISelectionService));
            if (selection != null && comp != null)
            {
                ArrayList arr = new ArrayList(1);
                arr.Add(comp);
                selection.SetSelectedComponents(arr, selectionType);
            }
        }
        private DesignerActionListCollection _ActionLists = null;
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (this._ActionLists == null)
                {
                    this._ActionLists = new DesignerActionListCollection();
                    this._ActionLists.Add(new ToolboxControlActionList(this));
                }
                return this._ActionLists;
            }
        }
        protected override void PreFilterProperties(System.Collections.IDictionary properties)
        {
            base.PreFilterProperties(properties);
            properties["Expanded"] = TypeDescriptor.CreateProperty(
                this.GetType(),
                "Expanded",
                typeof(bool),
                new Attribute[]
                {
                    new BrowsableAttribute(true), new DefaultValueAttribute(true),
                    new CategoryAttribute("Appearance"),
                    new DescriptionAttribute(
                        "Indicates whether control is expanded and shows items in full size with images and text")
                });
        }
        /// 
        /// Indicates whether Bar is in auto-hide state.
        /// 
        public bool Expanded
        {
            set
            {
                ShadowProperties["Expanded"] = value;
            }
            get
            {
                return (bool)ShadowProperties["Expanded"];
            }
        }
        private void dh_LoadComplete(object sender, EventArgs e)
        {
            IDesignerHost dh = this.GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (dh != null)
                dh.LoadComplete -= new EventHandler(dh_LoadComplete);
#if !TRIAL
            string key = GetLicenseKey();
            ToolboxControl tc = (ToolboxControl)this.Control;
            if (key != "" && tc != null && tc.LicenseKey == "" && tc.LicenseKey != key)
                TypeDescriptor.GetProperties(tc)["LicenseKey"].SetValue(tc, key);
#endif
            this.RecalcLayout();
        }
        #region Licensing Stuff
#if !TRIAL
        private string GetLicenseKey()
        {
            string key = "";
            Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.LocalMachine;
            regkey = regkey.OpenSubKey("Software\\DevComponents\\Licenses", false);
            if (regkey != null)
            {
                object keyValue = regkey.GetValue("DevComponents.DotNetBar.DotNetBarManager2");
                if (keyValue != null)
                    key = keyValue.ToString();
            }
            return key;
        }
        
#endif
        #endregion
    }
    #region ToolboxItemActionList
    internal class ToolboxControlActionList : DesignerActionList
    {
        private ToolboxControlDesigner _Designer = null;
        /// 
        /// Initializes a new instance of the AdvTreeActionList class.
        /// 
        /// 
        public ToolboxControlActionList(ToolboxControlDesigner designer)
            : base(designer.Component)
        {
            _Designer = designer;
        }
        public override DesignerActionItemCollection GetSortedActionItems()
        {
            DesignerActionItemCollection items = new DesignerActionItemCollection();
            items.Add(new DesignerActionHeaderItem("Items"));
            items.Add(new DesignerActionHeaderItem("Position"));
            items.Add(new DesignerActionMethodItem(this, "CreateGroup", "Create Group", "Items", true));
            //items.Add(new DesignerActionMethodItem(this, "MoveItemDown", "Move Down", "Position", true));
            items.Add(new DesignerActionPropertyItem("Expanded", "Toolbox Expanded?", "Behavior", "Indicates whether toolbox control is expanded and displays items at their full size."));
            items.Add(new DesignerActionPropertyItem("ItemDragDropEnabled", "Item Drag and Drop?", "Behavior", "Indicates whether item drag and drop is enabled."));
            items.Add(new DesignerActionPropertyItem("SearchBoxVisible", "Search Visible?", "Appearance", "Indicates whether search text-box is visible."));
            items.Add(new DesignerActionPropertyItem("TitleVisible", "Title Visible?", "Appearance", "Indicates whether title bar is visible."));
            items.Add(new DesignerActionPropertyItem("MenuVisible", "Menu Visible?", "Appearance", "Indicates whether menu bar is visible."));
            return items;
        }
        public void CreateGroup()
        {
            _Designer.CreateGroup();
        }
        public bool Expanded
        {
            get { return _Designer.Expanded; }
            set { _Designer.Expanded = value; }
        }
        public bool ItemDragDropEnabled
        {
            get { return ToolboxControl.ItemDragDropEnabled; }
            set { TypeDescriptor.GetProperties(base.Component)["ItemDragDropEnabled"].SetValue(base.Component, value); }
        }
        public bool SearchBoxVisible
        {
            get { return ToolboxControl.SearchBoxVisible; }
            set { TypeDescriptor.GetProperties(base.Component)["SearchBoxVisible"].SetValue(base.Component, value); }
        }
        public bool TitleVisible
        {
            get { return ToolboxControl.TitleVisible; }
            set { TypeDescriptor.GetProperties(base.Component)["TitleVisible"].SetValue(base.Component, value); }
        }
        public bool MenuVisible
        {
            get { return ToolboxControl.MenuVisible; }
            set { TypeDescriptor.GetProperties(base.Component)["MenuVisible"].SetValue(base.Component, value); }
        }
        public ToolboxControl ToolboxControl
        {
            get { return (ToolboxControl)this.Component; }
        }
    }
    #endregion
    /// 
    /// Support for TabStrip tabs design-time editor.
    /// 
    public class ToolboxControlGroupsEditor : CollectionEditor
    {
        public ToolboxControlGroupsEditor(Type type)
            : base(type)
        {
        }
        protected override Type CreateCollectionItemType()
        {
            return typeof(ToolboxGroup);
        }
        protected override Type[] CreateNewItemTypes()
        {
            return new Type[] { typeof(ToolboxGroup) };
        }
        protected override object CreateInstance(Type itemType)
        {
            object item = base.CreateInstance(itemType);
            if (item is ToolboxGroup)
            {
                ToolboxGroup tabItem = item as ToolboxGroup;
                tabItem.Text = "Group";
            }
            return item;
        }
    }
}