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

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using DevExpress.XtraBars;
using Framework.BaseUI;

namespace Framework.MainUI
{
	[DebuggerStepThrough]
	public class MainMenu
	{
		private Bar mainMenu;
		private Action<BarButtonMenu> menuItemClickEvent;

		public MainMenu(Bar mainMenu, Action<BarButtonMenu> menuItemCallMethod)
		{
			this.mainMenu = mainMenu;
			this.menuItemClickEvent = menuItemCallMethod;
			this.mainMenu.OptionsBar.AllowQuickCustomization = false;
		}

		public void BuildMenuTree(List<RootModuleAttribute> rootModuleList, List<ModuleInfo> moduleInfoList)
		{
			this.mainMenu.LinksPersistInfo.Clear();
			this.mainMenu.Manager.Items.Clear();

			SortModule(rootModuleList, moduleInfoList);

			//生成顶级菜单，它们的信息从DLL文件的Assembly.cs文件中获取
			foreach (RootModuleAttribute rootModule in rootModuleList)
			{
				if (!rootModule.ShowInMenu)
				{
					continue;
				}

				BarSubItem topMenu = new BarSubItem();
				topMenu.Caption = rootModule.Name;
				topMenu.Name = "menu" + rootModule.Name;

				mainMenu.Manager.Items.Add(topMenu);
				mainMenu.LinksPersistInfo.Add(new LinkPersistInfo(topMenu));
			}

			//生成模块菜单，它们从*.cs文件中的ModuleInfoAttribute中获取
			foreach (ModuleInfo moduleInfo in moduleInfoList)
			{
				if (!moduleInfo.Attribute.ShowInMenu) //如果指定模块不显示在菜单中，那么跳过
				{
					continue;
				}

				string[] menuNames = AnalyseMenuName(moduleInfo); //父菜单名与子菜单名以“点”字符分隔

				BarSubItem topMenu = GetTopMenuItem(menuNames[0]); //查找顶级菜单

				if (topMenu == null) //如果顶级菜单是空，那么建立整个菜单列表
				{
					BuildMenuList(null, menuNames, moduleInfo);
					continue;
				}
				else //否则建立顶级菜单下面的子菜单
				{
					BarSubItem parentMenu = topMenu;
					string[] subMenuName = menuNames;
					for (int i = 1; i < menuNames.Length; i++) //因为父菜单已经生成了，所以这里从二级菜单开始生成
					{
						subMenuName = RemoveFirst(subMenuName); //忽略已经生成的上级菜单
						BarSubItem subMenu = GetSubMenuItem(subMenuName[0], parentMenu); //查找下一级的子菜单是否已经建立
						if (subMenu == null)
						{
							BuildMenuList(parentMenu, subMenuName, moduleInfo); //如果子菜单没有建立，那么建立整个子菜单列表
							break;
						}
						parentMenu = subMenu; //如果子菜单已经建立了，那么把子菜单当作父菜单，继续查找下一级子菜单是否已经建立
					}
				}
			}

			// 隐藏不是必须的选项
			//if (isContract)
			//{
			//    ContractMenuItem(mainMenu.LinksPersistInfo);
			//}
		}

		/// <summary>
		/// 隐藏不是必须的选项
		/// </summary>
		private bool ContractMenuItem(LinksInfo linksPersistInfo)
		{
			foreach (LinkPersistInfo link in linksPersistInfo)
			{
				if (link.Item is BarSubItem)
				{
					BarSubItem subItem = link.Item as BarSubItem;
					ContractMenuItem(subItem.LinksPersistInfo);

					if (IsHideItem(subItem.LinksPersistInfo))
					{
						BarStaticItem menu = new BarStaticItem();
						menu.Caption = "更多功能";
						menu.ItemClick += this.showAll_ItemClick;
						menu.Tag = subItem;
						menu.ImageIndex = 0;

						menu.PaintStyle = BarItemPaintStyle.CaptionGlyph;

						mainMenu.Manager.Items.Add(menu);
						subItem.LinksPersistInfo.Add(new LinkPersistInfo(menu, true));
					}
				}
			}

			return false;
		}

		/// <summary>
		/// 是否有隐藏的按钮
		/// </summary>
		private bool IsHideItem(LinksInfo linksPersistInfo)
		{
			int i = 0;
			foreach (LinkPersistInfo link in linksPersistInfo)
			{
				if (link.Item is BarButtonMenu)
				{
					if (link.Item.Visibility == BarItemVisibility.Never)
					{
						i++;
					}
				}
			}

			if (i == linksPersistInfo.Count)
			{
				if (linksPersistInfo.Count > 0)
				{
					linksPersistInfo[0].Visible = true;
					linksPersistInfo[0].Item.Visibility = BarItemVisibility.Always;
				}
				return true;
			}

			if (i == 0)
			{
				return false;
			}

			return true;
		}

		private void showAll_ItemClick(object sender, ItemClickEventArgs e)
		{
			BarStaticItem item = e.Item as BarStaticItem;
			BarSubItem link = item.Tag as BarSubItem;

			//显示所有的菜单
			ShowAllMenuItem(mainMenu.LinksPersistInfo);
			//ShowAllMenuItem(link.LinksPersistInfo);
			item.Visibility = BarItemVisibility.Never;
		}

		/// <summary>
		/// 显示所有的菜单
		/// </summary>
		private void ShowAllMenuItem(LinksInfo items)
		{
			foreach (LinkPersistInfo link in items)
			{
				link.Visible = true;
				if (link.Item is BarSubItem)
				{
					BarSubItem item = link.Item as BarSubItem;
					item.Visibility = BarItemVisibility.Always;
					ShowAllMenuItem(item.LinksPersistInfo);
				}
			}
			foreach (LinkPersistInfo link in items)
			{
				link.Visible = true;
				if (link.Item is BarStaticItem)
				{
					link.Item.Visibility = BarItemVisibility.Never;
				}
				if (link.Item is BarButtonMenu)
				{
					link.Item.Visibility = BarItemVisibility.Always;
				}
			}
		}

		private void BuildMenuList(BarSubItem parentMenu, string[] menuNames, ModuleInfo moduleInfo)
		{
			BarSubItem pItem0 = parentMenu;
			for (int i = 0; i < menuNames.Length; i++)
			{
				if (parentMenu == null) //如果是要建立顶级菜单
				{
					parentMenu = new ModuleBarItem();
					parentMenu.Caption = menuNames[0]; //顶级菜单只是虚拟菜单，并不对应业务模块，只需要显示模块名称即可

					mainMenu.Manager.Items.Add(parentMenu);
					parentMenu.LinksPersistInfo.Add(new LinkPersistInfo(parentMenu));
				}
				else
				{
					if (menuNames.Length > 1 && i != menuNames.Length - 1)
					{
						if (GetParentItem(menuNames[i], menuNames, parentMenu) != null)
						{
							continue;
						}

						BarSubItem subItem = new BarSubItem();
						subItem.Caption = menuNames[i];

						mainMenu.Manager.Items.Add(subItem);
						if (i == 0)
						{
							parentMenu.LinksPersistInfo.Add(new LinkPersistInfo(subItem, moduleInfo.Attribute.HR));
						}
						else
						{
							BarSubItem pItem = GetParentItem(menuNames[i - 1], menuNames, parentMenu);
							pItem.LinksPersistInfo.Add(new LinkPersistInfo(subItem, moduleInfo.Attribute.HR));
						}
						pItem0 = subItem;
					}
					else
					{
						BarButtonMenu menu = new BarButtonMenu();

						menu.Caption = menuNames[i];
						if ((i == menuNames.Length - 1) && (moduleInfo != null)) //最后一个子菜单才对应有效的业务模块（窗体）
						{
							if (moduleInfo.Attribute.ShortcutKey != Keys.None)
							{
								menu.ItemShortcut = new BarShortcut(moduleInfo.Attribute.ShortcutKey);
							}
							menu.ModuleInfo = moduleInfo;
							menu.DllName = moduleInfo.DllPath;
							menu.ClassName = moduleInfo.FullClassName;
							menu.NodeName = moduleInfo.Attribute.Name;

							//如果模块有运行权限，那么菜单可进入。
							if (moduleInfo.CanRun)
							{
								menu.Enabled = true;
								menu.ItemClick += new ItemClickEventHandler(menu_ItemClick);
							}
							else
							{
								menu.Enabled = false;
								menu.Visibility = BarItemVisibility.Never; //没有权限的菜单不显示。
							}
						}

						mainMenu.Manager.Items.Add(menu);

						if (menuNames.Length > 1)
						{
							BarSubItem subItem = GetParentItem(menuNames[i - 1], menuNames, parentMenu);
							if (subItem != null)
							{
								subItem.LinksPersistInfo.Add(new LinkPersistInfo(menu, moduleInfo.Attribute.HR));
							}
						}
						else
						{
							parentMenu.LinksPersistInfo.Add(new LinkPersistInfo(menu, moduleInfo.Attribute.HR));
						}

					}
				}
			}
			//parentMenu.Visibility = parentMenu.LinksPersistInfo.Count > 0 ? BarItemVisibility.Always : BarItemVisibility.Never;
		}

		private void menu_ItemClick(object sender, ItemClickEventArgs e)
		{
			if (menuItemClickEvent != null)
			{
				menuItemClickEvent(e.Item as BarButtonMenu);
			}
		}

		//判断指定的根菜单是否已经生成，如果已经生成，那么返回它，否则返回null
		private BarSubItem GetTopMenuItem(string menuName)
		{
			foreach (LinkPersistInfo item in mainMenu.LinksPersistInfo)
			{
				if ((item.Item).Caption == menuName)
				{
					return item.Item as BarSubItem;
				}
			}
			return null;
		}

		private BarSubItem GetParentItem(string menuName, BarSubItem parentMenu)
		{
			foreach (LinkPersistInfo item in parentMenu.LinksPersistInfo)
			{
				if ((item.Item).Caption == menuName)
				{
					return item.Item as BarSubItem;
				}
			}
			return null;
		}

		private BarSubItem GetParentItem(string menuName, string[] menuNames, BarSubItem parentMenu)
		{
			if (parentMenu.Caption == menuName)
			{
				return parentMenu;
			}

			List<BarSubItem> lst = new List<BarSubItem>();
			lst.Add(parentMenu);
			for (int i = 0; i < menuNames.Length; i++)
			{
				BarSubItem item = GetParentItem(menuNames[i], lst[lst.Count - 1]);
				if (item != null)
				{
					lst.Add(item);
				}
			}

			foreach (BarSubItem item in lst)
			{
				if (item.Caption == menuName)
				{
					return item;
				}
			}

			return null;
		}

		private BarSubItem GetSubMenuItem(string menuName, BarSubItem parentMenu)
		{
			foreach (LinkPersistInfo item in parentMenu.LinksPersistInfo)
			{
				if ((item.Item).Caption == menuName)
				{
					return item.Item as BarSubItem;
				}
			}
			return null;
		}

		private void SortModule(List<RootModuleAttribute> rootModuleList, List<ModuleInfo> moduleInfoList)
		{
			rootModuleList.Sort(delegate(RootModuleAttribute a, RootModuleAttribute b)
			{
				if (a.Order > b.Order)
				{
					return 1;
				}
				else if (a.Order == b.Order)
				{
					return 0;
				}
				else
				{
					return -1;
				}
			});

			moduleInfoList.Sort(delegate(ModuleInfo a, ModuleInfo b)
			{
				if (a.Attribute.Order > b.Attribute.Order)
				{
					return 1;
				}
				else if (a.Attribute.Order == b.Attribute.Order)
				{
					return 0;
				}
				else
				{
					return -1;
				}
			});
		}

		private string[] AnalyseMenuName(ModuleInfo moduleInfo)
		{
			string s = "";
			string[] list = moduleInfo.Attribute.Name.Split('.');
			if (!string.IsNullOrEmpty(moduleInfo.Attribute.RootModule) && moduleInfo.Attribute.RootModule != list[0])
			{
				s = moduleInfo.Attribute.RootModule + "." + moduleInfo.Attribute.Name;
			}
			else
			{
				s = moduleInfo.Attribute.Name;
			}
			return s.Split('.');
		}

		//把字符串数组的第一项删除
		private string[] RemoveFirst(string[] s)
		{
			string[] newArray = new string[s.Length - 1];
			for (int i = 0; i < newArray.Length; i++)
			{
				newArray[i] = s[i + 1];
			}
			return newArray;
		}
	}
}
