//==============================================================
//  版权所有：深圳杰文科技
//  文件名：Toolbar.cs
//  版本：V1.0  
//  创建者：Jay  ( QQ： 85363208 )
//  创建时间：2017-11-28 16:18
//  创建描述：
//  修改者：
//  修改时间：
//  修改说明： 
//==============================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using DevExpress.Utils;
using DevExpress.XtraBars;
using System.Resources;

namespace Framework.BaseUI
{
	//[DebuggerStepThrough]
	public class Toolbar
	{
		#region 构造函数

		public Toolbar()
		{
		}

		public Toolbar(Bar bar)
			: this()
		{
			this.Bar = bar;
			this.Bar.OptionsBar.AllowDelete = false;
			this.Bar.OptionsBar.AllowQuickCustomization = false;
			this.Bar.OptionsBar.AllowRename = false;
			this.Bar.OptionsBar.MultiLine = true;
			this.Bar.OptionsBar.DisableClose = true;
			this.Bar.OptionsBar.DisableCustomization = true;
			this.Bar.OptionsBar.MultiLine = true;
		}

		#endregion

		#region 按钮管理

		public void Enable()
		{
			foreach (LinkPersistInfo link in this.Bar.LinksPersistInfo)
			{
				BarActionButton button = link.Item as BarActionButton;
				if (button == null)
				{
					continue;
				}

				if (button.IsPrivilege)
				{
					button.Enabled = this.HasPrivilege(button);
				}
				else
				{
					button.Enabled = true;
				}
			}
		}

		public void Disable()
		{
			foreach (LinkPersistInfo link in this.Bar.LinksPersistInfo)
			{
				BarActionButton button = link.Item as BarActionButton;
				if (button == null)
				{
					continue;
				}

				if (button.Name != "Close") //关闭按钮在任何时候都有效的
				{
					button.Enabled = false;
				}
			}
		}

		/// <summary>
		/// 启用按钮，actions是方法的名称，或者是方法的标题
		/// </summary>
		/// <param name="actions"></param>
		public void EnableButton(params Action[] actions)
		{
			foreach (Action action in actions)
			{
				BarActionButton button = FindButton(action.Method.Name);
				if (button == null) //如果在工具栏上没有找到对应的按钮
				{
					continue;
				}

				//必须有权限，才能让按钮可用
				button.Enabled = this.HasPrivilege(button);
			}
		}

		/// <summary>
		/// 禁止按钮，actions是方法的名称，或者是方法的标题
		/// </summary>
		/// <param name="actions"></param>
		public void DisableButton(params Action[] actions)
		{
			foreach (Action action in actions)
			{
				BarActionButton button = FindButton(action.Method.Name);
				if (button != null) //如果在工具栏上找到对应的按钮
				{
					button.Enabled = false;
				}
			}
		}

		public void ShowButton(params Action[] actions)
		{
			foreach (Action action in actions)
			{
				BarActionButton button = FindButton(action.Method.Name);
				if (button != null) //如果在工具栏上找到对应的按钮
				{
					button.Visibility = BarItemVisibility.Always;
				}
			}
		}

		/// <summary>
		/// 隐藏指定的若干个按钮。
		/// </summary>
		public void HideButton(params Action[] actions)
		{
			foreach (Action action in actions)
			{
				BarActionButton button = FindButton(action.Method.Name);
				if (button != null) //如果在工具栏上找到对应的按钮
				{
					//if (button.Caption == "关闭")
					//{
					//	continue;
					//}
					button.Visibility = BarItemVisibility.Never;
				}
			}
		}

		protected internal BarActionButton FindButton(string action)
		{
			BarActionButton button;

			//如果传进来的有中文字符，那么查找按钮标题, 否则查找名称
			Dictionary<string, BarActionButton> dictionary = GetAllButtonsByName();
			dictionary.TryGetValue(action, out button);

			return button;
		}

		private Dictionary<string, BarActionButton> GetAllButtonsByName()
		{
			Dictionary<string, BarActionButton> dictionary = new Dictionary<string, BarActionButton>();

			foreach (LinkPersistInfo link in this.Bar.LinksPersistInfo)
			{
				BarActionButton button;
				BarSubItem barSubItem;

				if ((button = link.Item as BarActionButton) != null)
				{
					dictionary.Add(button.MethodName, button);
				}
				else if ((barSubItem = link.Item as BarSubItem) != null)
				{
					foreach (LinkPersistInfo subLink in barSubItem.LinksPersistInfo)
					{
						button = subLink.Item as BarActionButton;
						if (button != null)
						{
							dictionary.Add(button.MethodName, button);
						}
					}
				}
			}

			return dictionary;
		}

		private Dictionary<string, BarActionButton> GetAllButtonsByCaption()
		{
			Dictionary<string, BarActionButton> dictionary = new Dictionary<string, BarActionButton>();

			foreach (LinkPersistInfo link in this.Bar.LinksPersistInfo)
			{
				BarActionButton button;
				BarSubItem barSubItem;
				if ((button = link.Item as BarActionButton) != null)
				{
					dictionary.Add(button.Caption, button);
				}
				else if ((barSubItem = link.Item as BarSubItem) != null)
				{
					foreach (LinkPersistInfo subLink in barSubItem.LinksPersistInfo)
					{
						button = subLink.Item as BarActionButton;
						if (button != null)
						{
							dictionary.Add(button.Caption, button);
						}
					}
				}
			}

			return dictionary;
		}

		private void button_ItemClick(object sender, ItemClickEventArgs e)
		{
			BarActionButton button = e.Item as BarActionButton;
			button.MethodDelegate();
		}

		private void button_Click(object sender, EventArgs e)
		{
			BarActionButton button = sender as BarActionButton;
			button.MethodDelegate();
		}

		public void RemoveButton(MethodInvoker methodDelegate)
		{
			BarActionButton button = FindButton(methodDelegate.Method.Name);
			if (button != null)
			{
				button.Visibility = BarItemVisibility.Never;
			}
		}

		#endregion

		#region 公共属性

		public ModuleInfo ModuleInfo
		{
			get;
			set;
		}

		public ImageCollection ImageList
		{
			get;
			set;
		}

		public BarManager BarManager
		{
			get;
			set;
		}

		public Bar Bar
		{
			get;
			set;
		}

		private IBaseForm form;

		public IBaseForm Form
		{
			get
			{
				return form;
			}
			set
			{
				form = value;
				this.ModuleInfo = ModuleParser.Instance.GetModuleInfo(form.GetType().FullName);
			}
		}

		#endregion

		#region 建立工具栏按钮

		/// <summary>
		/// 构造Toolbar按钮。
		/// </summary>
		public void BuildToolbar()
		{
			if (this.Bar == null)
			{
				MessageBox.Show("bar不能为空！");
			}

			this.Bar.Manager.Items.Clear();
			this.Bar.ItemLinks.Clear();
			this.Bar.LinksPersistInfo.Clear();

			//得到窗体所有定义了MethodPropertyAttribute的方法的属性值列表。
			List<ActionAttribute> propertyList = ModuleParser.Instance.GetMethodPropertyList(this.form.GetType());

			//当前模块是否接受权限管理。
			bool isPrivilege = this.ModuleInfo != null && this.ModuleInfo.Attribute.Permission;

			// 构建工具栏按钮列表。
			CreateButtonList(isPrivilege, propertyList);
		}

		private void CreateButtonList(bool isPrivilege, List<ActionAttribute> propertyList)
		{
			//先创建非下拉子按钮。
			List<ActionAttribute> list1 = propertyList.Where(a => string.IsNullOrEmpty(a.ParentItem)).ToList();
			CreateButtonList2(isPrivilege, list1);

			//再创建下拉子按钮。
			List<ActionAttribute> list2 = propertyList.Where(a => !string.IsNullOrEmpty(a.ParentItem)).ToList();
			CreateButtonList2(isPrivilege, list2);
		}

		private void CreateButtonList2(bool isPrivilege, List<ActionAttribute> propertyList)
		{
			for (int i = 0; i <= propertyList.Count - 1; i++)
			{
				ActionAttribute property = propertyList[i];
				if (!property.ShowInToolbar) //当前功能不需要显示在工具栏中
				{
					continue;
				}

				if (property.SubItem) //如果是下拉按钮的父按钮；
				{
					string imageName = string.IsNullOrEmpty(property.Image) ? property.Method.Name : property.Image;
					BarSubItem dropDownButton = new BarSubItem();
					dropDownButton.PaintStyle = BarItemPaintStyle.CaptionGlyph;
					dropDownButton.Caption = property.Name;
					dropDownButton.Glyph = this.ImageList.Images[imageName];

					if (property.BeginGroup) //如果前面有分隔条
					{
						this.Bar.ItemLinks.Add(dropDownButton, true);
					}
					else
					{
						this.Bar.ItemLinks.Add(dropDownButton);
					}
				}
				else
				{
					CreateButton(isPrivilege, property);
				}
			}

		}

		private void CreateButton(bool isPrivilege, ActionAttribute property)
		{
			string imageName = string.IsNullOrEmpty(property.Image) ? property.Method.Name.ToLower() : property.Image.ToLower();

			BarActionButton button = new BarActionButton();
			button.Tag = property;
			button.Glyph = this.ImageList.Images[imageName];
			button.PaintStyle = BarItemPaintStyle.CaptionGlyph;
			button.Caption = string.IsNullOrEmpty(property.Caption) ? property.Name : property.Caption;
			button.Appearance.Font = new Font(ClientContext.FontName, ClientContext.FontSize);

			if (property.ShortcutKey != Keys.None)
			{
				button.Caption += property.ShortcutKey.ToString();
			}

			button.Name = "action" + property.Method.Name; //action前缀 + 方法名 = 按钮名称
			button.IsPrivilege = property.Permission; //此按钮是否接受权限管理
			button.MethodName = property.Method.Name;
			button.Method = property.Method;

			//如果系统报告“绑定到目标方法时出错”，请确定被调用窗体的方法，必须没有参数和返回值。
			//因为MethodInvoker类型的委托，必须是无参数且无返回值
			button.MethodDelegate = (MethodInvoker)Delegate.CreateDelegate(typeof(MethodInvoker), this.form, property.Method.Name);

			button.ItemShortcut = new BarShortcut(property.ShortcutKey);
			button.HasPrivilege = !isPrivilege || this.HasPrivilege(button); //检查按钮的权限
			button.Enabled = button.HasPrivilege;
			if (button.HasPrivilege)
			{
				button.ItemClick += new ItemClickEventHandler(delegate(object sender, ItemClickEventArgs e)
				{
					button.MethodDelegate();
				});
			}

			//存在父下拉按钮
			if (!string.IsNullOrEmpty(property.ParentItem))
			{
				//找到父下拉按钮
				foreach (BarItemLink item in this.Bar.ItemLinks)
				{
					if (item.Item.Caption == property.ParentItem)
					{
						BarSubItem subItem = item.Item as BarSubItem;

						if (property.BeginGroup)
						{
							subItem.ItemLinks.Add(button, true);
						}
						else
						{
							subItem.ItemLinks.Add(button);
						}
						break;
					}
				}
				return;
			}
			else
			{
				if (property.BeginGroup) //如果前面有分隔条
				{
					this.Bar.ItemLinks.Add(button, true);
				}
				else
				{
					this.Bar.ItemLinks.Add(button);
				}
			}
		}

		#endregion

		//判断按钮是否有权限
		private bool HasPrivilege(BarActionButton button)
		{
			if (this.ModuleInfo == null)
			{
				return true;
			}

			ActionAttribute property = button.Tag as ActionAttribute;
			if (property == null)
			{
				return true;
			}

			if (!property.Permission)
			{
				return true;
			}

			return PermissionManager.Instance.HasPermission(this.ModuleInfo, property.Name);
		}

		/// <summary>
		/// 除了参数指定的按钮，显示所有按钮。
		/// </summary>
		/// <param name="excludeActions"></param>
		public void ShowAll(params Action[] excludeActions)
		{
			Dictionary<string, BarActionButton> dictionary = GetAllButtonsByName();
			foreach (KeyValuePair<string, BarActionButton> kvp in dictionary)
			{
				if (kvp.Key == "CloseForm" || kvp.Key == "RestoreCustomStyle")
				{
					continue;
				}

				bool found = false;
				foreach (Action action in excludeActions)
				{
					if (action.Method.Name == kvp.Key)
					{
						found = true;
						break;
					}
				}

				if (found)
				{
					kvp.Value.Visibility = BarItemVisibility.Never;
				}
				else
				{
					kvp.Value.Visibility = BarItemVisibility.Always;
				}
			}
		}

		/// <summary>
		/// 只显示某几个按钮，隐藏其余按钮。
		/// </summary>
		public void ShowOnly(params Action[] actions)
		{
			Dictionary<string, BarActionButton> dictionary = GetAllButtonsByName();
			foreach (KeyValuePair<string, BarActionButton> kvp in dictionary)
			{
				if (kvp.Key == "CloseForm" || kvp.Key == "RestoreCustomStyle")
				{
					continue;
				}

				bool found = false;
				foreach (Action action in actions)
				{
					if (action.Method.Name == kvp.Key)
					{
						found = true;
						break;
					}
				}

				if (found)
				{
					kvp.Value.Visibility = BarItemVisibility.Always;
				}
				else
				{
					kvp.Value.Visibility = BarItemVisibility.Never;
				}
			}
		}

		/// <summary>
		/// 隐藏所有按钮
		/// </summary>
		public void HideAll()
		{
			foreach (LinkPersistInfo link in this.Bar.LinksPersistInfo)
			{
				BarActionButton btn = link.Item as BarActionButton;
				if (btn == null || btn.Caption == "关闭")
				{
					continue;
				}

				btn.Visibility = BarItemVisibility.Never;
			}
		}

		/// <summary>
		/// 隐藏工具栏。
		/// </summary>
		public void HideBar()
		{
			this.Bar.Visible = false;
		}

		/// <summary>
		/// 反转控制，只读时隐藏指定的按钮，非只读时只显示指定的按钮。
		/// </summary>
		/// <param name="readOnly"></param>
		/// <param name="actions"></param>
		public void EditMode(bool readOnly, params Action[] actions)
		{
			if (readOnly)
			{
				HideButton(actions);
			}
			else
			{
				ShowOnly(actions);
			}
		}

		//给按钮设置资源里的图片。
		public void SetImage(Action action, Image image)
		{
			BarActionButton button = FindButton(action.Method.Name);
			if (button == null || image == null)
			{
				return;
			}

			button.Glyph = image;
		}

		//设置按钮标签。
		public void SetCaption(Action action, string caption)
		{
			BarActionButton button = FindButton(action.Method.Name);
			if (button == null || image == null)
			{
				return;
			}

			button.Caption = caption;
		}

		#region - 工具栏按图片名称 -

		public const string add = "add";
		public const string ok = "ok";
		public const string cancel = "cancel";
		public const string closeform = "closeform";
		public const string refreshdata = "refreshdata";
		public const string delete = "delete";
		public const string open = "open";
		public const string undo = "undo";
		public const string redo = "redo";
		public const string remove = "remove";
		public const string barcode = "barcode";
		public const string audit = "audit";
		public const string image = "image";
		public const string remark = "remark";
		public const string summary = "summary";
		public const string modify = "modify";
		public const string export = "export";
		public const string find = "find";
		public const string upload = "upload";
		public const string user = "user";
		public const string usergroup = "usergroup";
		public const string preview = "preview";
		public const string print = "print";
		public const string config = "config";
		public const string save = "save";
		public const string setting = "setting";
		public const string query = "query";
		public const string idcard = "idcard";
		public const string browse = "browse";
		public const string import = "import";
		public const string wizard = "wizard";
		public const string attach = "attach";
		public const string disable = "disable";
		public const string tag = "tag";
		public const string history = "history";
		public const string gauges = "gauges";
		public const string car = "car";
		public const string paste = "paste";
		public const string sendmsg = "sendmsg";
		public const string feed = "feed";
		public const string item = "item";
		public const string selectall = "item";
		public const string chart = "chart";
		public const string up = "up";
		public const string down = "down";
		public const string prev = "prev";
		public const string next = "next";

		#endregion
	}
}
