using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Drawing.Text;
using System.Windows.Forms;
namespace DevComponents.DotNetBar
{
	/// 
	/// Represents class with static functions that provide commonly used utility functions when working with
	/// Bar objects and items hosted by Bar object.
	/// 
	public class BarUtilities
    {
        #region Docking
        /// 
        /// Sets Bar visible property and remembers the auto-hide state.
        /// 
        /// Bar to set visibility for.
        /// true if visible otherwise false
        public static void SetBarVisible(Bar bar, bool visible)
        {
            if (bar == null || bar.Visible == visible)
                return;
            DotNetBarManager manager = bar.Owner as DotNetBarManager;
            if (manager != null)
                manager.SuspendLayout = true;
            try
            {
                if (visible)
                {
                    bar.Visible = true;
                    if (bar.PropertyBag.ContainsKey(BarPropertyBagKeys.AutoHideSetting))
                    {
                        bar.PropertyBag.Remove(BarPropertyBagKeys.AutoHideSetting);
                        bar.AutoHide = true;
                    }
                }
                else
                {
                    if (bar.PropertyBag.ContainsKey(BarPropertyBagKeys.AutoHideSetting))
                        bar.PropertyBag.Remove(BarPropertyBagKeys.AutoHideSetting);
                    // Remember auto-hide setting
                    if (bar.AutoHide)
                        bar.PropertyBag.Add(BarPropertyBagKeys.AutoHideSetting, true);
                    bar.CloseBar();
                }
            }
            finally
            {
                if (manager != null)
                    manager.SuspendLayout = false;
                bar.RecalcLayout();
            }
        }
        /// 
		/// Sets the visible property of DockContainerItem and hides the bar if the given item is the last visible item on the bar.
		/// It will also automatically display the bar if bar is not visible.
		/// 
		/// DockContainerItem to set visibility for.
		/// Indicates the visibility of the item
		public static void SetDockContainerVisible(DevComponents.DotNetBar.DockContainerItem item, bool visible)
		{
			if(item==null || item.Visible==visible)
				return;
			DevComponents.DotNetBar.Bar containerBar=item.ContainerControl as DevComponents.DotNetBar.Bar;
			if(containerBar==null)
			{
				// If bar has not been assigned yet just set the visible property and exit
				item.Visible=visible;
				return;
			}
			DotNetBarManager manager=containerBar.Owner as DotNetBarManager;
			if(manager!=null)
				manager.SuspendLayout=true;
			try
			{
				int visibleCount=containerBar.VisibleItemCount;
				if(visible)
				{
					item.Visible=true;
					if(!containerBar.AutoHide && !containerBar.Visible && visibleCount<=1)
					{
						containerBar.Visible=true;
						if(containerBar.PropertyBag.ContainsKey(BarPropertyBagKeys.AutoHideSetting))
						{
							containerBar.PropertyBag.Remove(BarPropertyBagKeys.AutoHideSetting);
							containerBar.AutoHide=true;
						}
					}
				}
				else
				{
                    if (visibleCount <= 1)
                    {
                        if (containerBar.PropertyBag.ContainsKey(BarPropertyBagKeys.AutoHideSetting))
                            containerBar.PropertyBag.Remove(BarPropertyBagKeys.AutoHideSetting);
                        // Remember auto-hide setting
                        if (containerBar.AutoHide)
                            containerBar.PropertyBag.Add(BarPropertyBagKeys.AutoHideSetting, true);
                        containerBar.CloseBar();
                    }
					item.Visible=false;
				}
			}
			finally
			{
				if(manager!=null)
					manager.SuspendLayout=false;
				containerBar.RecalcLayout();
			}
		}
		/// 
		/// Creates new instance of the bar and sets its properties so bar can be used as Document bar.
		/// 
		/// Returns new instance of the bar.
		public static Bar CreateDocumentBar()
		{
			Bar bar=new Bar();
			BarUtilities.InitializeDocumentBar(bar);
			return bar;
		}
		/// 
		/// Sets the properties on a bar so it can be used as Document bar.
		/// 
		/// Bar to set properties of.
		public static void InitializeDocumentBar(Bar bar)
		{
			TypeDescriptor.GetProperties(bar)["LayoutType"].SetValue(bar,eLayoutType.DockContainer);
			TypeDescriptor.GetProperties(bar)["DockTabAlignment"].SetValue(bar,eTabStripAlignment.Top);
			TypeDescriptor.GetProperties(bar)["AlwaysDisplayDockTab"].SetValue(bar,true);
			TypeDescriptor.GetProperties(bar)["Stretch"].SetValue(bar,true);
			TypeDescriptor.GetProperties(bar)["GrabHandleStyle"].SetValue(bar,eGrabHandleStyle.None);
			TypeDescriptor.GetProperties(bar)["CanDockBottom"].SetValue(bar,false);
			TypeDescriptor.GetProperties(bar)["CanDockTop"].SetValue(bar,false);
			TypeDescriptor.GetProperties(bar)["CanDockLeft"].SetValue(bar,false);
			TypeDescriptor.GetProperties(bar)["CanDockRight"].SetValue(bar,false);
			TypeDescriptor.GetProperties(bar)["CanDockDocument"].SetValue(bar,true);
			TypeDescriptor.GetProperties(bar)["CanUndock"].SetValue(bar,false);
			TypeDescriptor.GetProperties(bar)["CanHide"].SetValue(bar,true);
			TypeDescriptor.GetProperties(bar)["CanCustomize"].SetValue(bar,false);
			TypeDescriptor.GetProperties(bar)["TabNavigation"].SetValue(bar,true);
        }
        #region Win API
        [DllImport("user32")]
        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
        [DllImport("user32")]
        private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
        private const int GWL_EXSTYLE = (-20);
        private const int WS_EX_CLIENTEDGE = 0x00000200;
        [DllImport("user32")]
        private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
        const int SWP_FRAMECHANGED = 0x0020;
        const int SWP_NOSIZE = 0x0001;
        const int SWP_NOMOVE = 0x0002;
        const int SWP_NOZORDER = 0x0004;
        #endregion
        /// 
        /// Changes the MDI Client border edge to remove 3D border or to add it.
        /// 
        /// Reference to MDI Client object.
        /// Indicates whether to remove border.
        public static void ChangeMDIClientBorder(System.Windows.Forms.MdiClient c, bool removeBorder)
        {
            if (c != null)
            {
                int exStyle = GetWindowLong(c.Handle, GWL_EXSTYLE);
                
                if(removeBorder)
                    exStyle ^= WS_EX_CLIENTEDGE;
                else
                    exStyle |= WS_EX_CLIENTEDGE;
                SetWindowLong(c.Handle, GWL_EXSTYLE, exStyle);
                SetWindowPos(c.Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
            }
        }
        /// 
        /// Changes the MDI Client border edge to remove 3D border or to add it.
        /// 
        /// Reference to MDI parent form.
        /// Indicates whether to remove border.
        public static void ChangeMDIClientBorder(System.Windows.Forms.Form c, bool removeBorder)
        {
            if (c.IsMdiContainer && c.IsHandleCreated)
            {
                foreach (System.Windows.Forms.Control control in c.Controls)
                {
                    if (control is System.Windows.Forms.MdiClient)
                    {
                        ChangeMDIClientBorder(control as System.Windows.Forms.MdiClient, removeBorder);
                        break;
                    }
                }
            }
        }
        #endregion
        #region Item Invalidate
        internal static void InvalidateFontChange(SubItemsCollection col)
        {
            foreach (BaseItem item in col)
            {
                InvalidateFontChange(item);
            }
        }
        internal static void InvalidateFontChange(BaseItem item)
        {
            if (item.TextMarkupBody != null) item.TextMarkupBody.InvalidateElementsSize();
            if (item.SubItems.Count > 0) InvalidateFontChange(item.SubItems);
        }
        #endregion
        internal static void InvokeRecalcLayout(System.Windows.Forms.Control control)
        {
            if (control is Bar)
                ((Bar)control).RecalcLayout();
            else if (control is ItemControl)
                ((ItemControl)control).RecalcLayout();
            else if (control is BaseItemControl)
                ((BaseItemControl)control).RecalcLayout();
            else if (control is ExplorerBar)
                ((ExplorerBar)control).RecalcLayout();
            else if (control is SideBar)
                ((SideBar)control).RecalcLayout();
        }
        private static volatile bool _FadeAnimatorEnabled = true;
        /// 
        /// Gets or sets whether Fade Animation is enabled on system level for DotNetBar items which use this. Default value is true.
        /// 
        public static bool FadeAnimatorEnabled
        {
            get { return _FadeAnimatorEnabled; }
            set { _FadeAnimatorEnabled = value; }
        }
        /// 
        /// Gets or sets whether StringFormat internally used by all DotNetBar controls to render text is GenericDefault. Default value is false
        /// which indicates that GenericTypographic is used.
        /// 
        public static bool UseGenericDefaultStringFormat
        {
            get { return TextDrawing.UseGenericDefault; }
            set { TextDrawing.UseGenericDefault = value; }
        }
        /// 
        /// Gets or sets the anti-alias text rendering hint that will be used to render text on controls that have AntiAlias property set to true.
        /// 
        public static TextRenderingHint AntiAliasTextRenderingHint
        {
            get
            {
                return DisplayHelp.AntiAliasTextRenderingHint;
            }
            set
            {
            	DisplayHelp.AntiAliasTextRenderingHint = value;
            }
        }
#if FRAMEWORK20
        /// 
        /// Gets or sets whether .NET Framework TextRenderer class is used for text rendering instead of Graphics.DrawString. 
        /// Default value is false. 
        /// Using TextRenderer will disable the Fade and Animation effects on controls because of issues in TextRenderer when drawing text on transparent
        /// surfaces.
        /// 
        public static bool UseTextRenderer
        {
            get { return TextDrawing.UseTextRenderer; }
            set { TextDrawing.UseTextRenderer = value; }
        }
#endif
        private static bool _AlwaysGenerateAccessibilityFocusEvent = false;
        /// 
        /// Gets or sets whether items always generate the Focus accessibility event when mouse enters the item. Default value is false which indicates
        /// that focus event will be raised only when item is on menu bar.
        /// 
        public static bool AlwaysGenerateAccessibilityFocusEvent
        {
            get { return _AlwaysGenerateAccessibilityFocusEvent; }
            set
            {
                _AlwaysGenerateAccessibilityFocusEvent = value;
            }
        }
        internal static bool IsModalFormOpen
        {
            get
            {
#if (FRAMEWORK20)
                for (int i = 0; i < System.Windows.Forms.Application.OpenForms.Count; i++)
                {
                    System.Windows.Forms.Form form = System.Windows.Forms.Application.OpenForms[i];
                    if (form.Modal) return true;
                }
#endif
                return false;
            }
        }
        private static bool _AutoRemoveMessageFilter = false;
        /// 
        /// Gets or sets whether Application Message Filter that is registered by popup controls
        /// is automatically unregistered when last control is disposed. Default value is false and
        /// in most cases should not be changed.
        /// 
        public static bool AutoRemoveMessageFilter
        {
            get { return _AutoRemoveMessageFilter; }
            set { _AutoRemoveMessageFilter = value; }
        }
        private static int _TextMarkupCultureSpecific = 3;
        /// 
        /// Get or sets the text-markup padding for text measurement when running on Japanese version of Windows.
        /// 
        public static int TextMarkupCultureSpecificPadding
        {
            get { return _TextMarkupCultureSpecific; }
            set
            {
                _TextMarkupCultureSpecific = value;
            }
        }
        private static bool _DisposeItemImages = false;
        /// 
        /// Gets or sets whether Image and Icon resources assigned to items and controls are automatically disposed when
        /// control or item is disposed. Default value is false.
        /// 
        public static bool DisposeItemImages
        {
            get
            {
                return _DisposeItemImages;
            }
            set
            {
                _DisposeItemImages = value;
            }
        }
        /// 
        /// Disposes image reference and sets it to null.
        /// 
        /// Reference to image to dispose.
        internal static void DisposeImage(ref System.Drawing.Image image)
        {
            if (image == null) return;
            image.Dispose();
            image = null;
        }
        /// 
        /// Disposes image reference and sets it to null.
        /// 
        /// Reference to image to dispose.
        internal static void DisposeImage(ref System.Drawing.Icon icon)
        {
            if (icon == null) return;
            icon.Dispose();
            icon = null;
        }
        #region Delayed Invoke
        /// 
        /// Invokes the method asynchronously using the WinForms Timer.
        /// 
        /// Method to invoke.
        public static void InvokeDelayed(MethodInvoker method)
        {
            InvokeDelayed(method, 10);
        }
        /// 
        /// Invokes the method asynchronously using the WinForms Timer.
        /// 
        /// Method to invoke.
        /// Time in milliseconds after which method is invoked.
        public static void InvokeDelayed(MethodInvoker method, int delayInterval)
        {
            Timer delayedInvokeTimer = new Timer();
            delayedInvokeTimer = new Timer();
            delayedInvokeTimer.Tag = method;
            delayedInvokeTimer.Interval = delayInterval;
            delayedInvokeTimer.Tick += new EventHandler(DelayedInvokeTimerTick);
            delayedInvokeTimer.Start();
        }
        private static void DelayedInvokeTimerTick(object sender, EventArgs e)
        {
            Timer timer = (Timer)sender;
            MethodInvoker method = (MethodInvoker)timer.Tag;
            timer.Stop();
            timer.Dispose();
            method.Invoke();
        }
        #endregion
    }
	internal class BarPropertyBagKeys
	{
		public static string AutoHideSetting="autohide";
	}
}