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

using System;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Forms;
using System.Collections.Generic;

namespace Framework.BaseUI
{
	/// <summary>
	/// 模块代理，负责所有的模块（窗体）的调用（创建）。
	/// </summary>
	//[DebuggerStepThrough]
	public class ModuleProxy
	{
		public readonly TabNavManager TabNavManager = new TabNavManager();
		private static Dictionary<string, Assembly> asmDict = new Dictionary<string, Assembly>();

		private ModuleProxy()
		{
		}

		public static readonly ModuleProxy Instance = new ModuleProxy();

		public static void Open<T>(string action, params object[] args) where T : Form
		{
			ModuleProxy.Instance.Execute(typeof(T), action, args);
		}

		public IMainForm MainForm
		{
			get;
			set;
		}

		public TForm ShowForm<TForm>() where TForm : BaseForm
		{
			Type type = typeof(TForm);
			return (TForm)ShowForm(type);
		}

		public BaseForm ShowForm(Type formType)
		{
			ModuleInfo moduleInfo = ModuleParser.Instance.GetModuleInfo(formType.FullName);
			Form form = ShowForm(true, moduleInfo, null, null);
			return form as BaseForm;
		}

		public void Execute(string module, string action, object[] args)
		{
			ModuleInfo moduleInfo = ModuleParser.Instance.GetModuleInfoByModuleName(module);
			if (moduleInfo == null)
			{
				throw new Exception(string.Format("找不到 {0}", module));
			}
			if (moduleInfo.CanRun)
			{
				Execute(false, moduleInfo, action, args);
			}
		}

		public void Execute(Type type, string action, params object[] args)
		{
			ModuleInfo moduleInfo = ModuleParser.Instance.GetModuleInfo(type.FullName);
			if (moduleInfo == null)
			{
				throw new Exception(string.Format("找不到 {0}", type.FullName));
			}
			Execute(false, moduleInfo, action, args);
		}

		public void Execute(bool manualCall, ModuleInfo moduleInfo, string action, object[] args)
		{
			if (!moduleInfo.CanRun)
			{
				return;
			}

			if (moduleInfo.Attribute.UI)
			{
				ShowForm(manualCall, moduleInfo, action, args);
			}
			else
			{
				Assembly asm = LoadAssembly(moduleInfo.DllPath);

				object obj = asm.CreateInstance(moduleInfo.FullClassName);
				if (string.IsNullOrEmpty(action) || action.ToLower() == "load")
				{
					return;
				}
				MethodInfo mi = obj.GetType().GetMethod(action);
				mi.Invoke(obj, args);
			}
		}

		internal Type LoadType(ModuleInfo moduleInfo)
		{
			Assembly asm = LoadAssembly(moduleInfo.DllPath);
			Type type = asm.GetType(moduleInfo.FullClassName, false);
			return type;
		}

		internal Assembly LoadAssembly(string dllPath)
		{
			Assembly asm = null;
			if (asmDict.ContainsKey(dllPath))
			{
				asm = asmDict[dllPath];
			}
			else
			{
				asm = Assembly.LoadFrom(dllPath);
				asmDict.Add(dllPath, asm);
			}
			return asm;
		}

		public Form ShowForm(bool manualCall, ModuleInfo moduleInfo, string action, object[] args)
		{
			if (moduleInfo == null)
			{
				return null;
			}
			if (moduleInfo.View == null || moduleInfo.View.IsDisposed)
			{
				Assembly asm = LoadAssembly(moduleInfo.DllPath);
				moduleInfo.View = asm.CreateInstance(moduleInfo.FullClassName) as IBaseForm;
				if (moduleInfo.View == null)
				{
					throw new Exception("创建View失败，请检查View是否实现了IBaseForm接口");
				}
				moduleInfo.View.ManualCall = manualCall;
				moduleInfo.View.ModuleName = moduleInfo.Attribute.Name;
			}

			Form destForm = moduleInfo.View as Form;

			if (!string.IsNullOrEmpty(action) && action.ToLower() != "运行")
			{
				MethodInfo mi = destForm.GetType().GetMethod(action);
				if (mi == null)
				{
					throw new Exception(string.Format("找不到{0}的{1}", moduleInfo.Attribute.Name, action));
				}

				if (destForm.Visible) //如果已经显示了，那么直接调用；
				{
					mi.Invoke(destForm, args);
				}
				else //否则在窗体显示之后调用。
				{
					destForm.Shown += (a, b) => mi.Invoke(destForm, args);
				}
			}

			//如果定义为弹出窗体，并且用户没有指定要以非模态方法显示，那么弹出显示，而且不用导航栏管理。
			if (moduleInfo.Attribute.Pop)
			{
				//注意，对于窗体界面的操作，尽量让MainForm去执行，这样发生异常时，才不会导致弹出窗体自动隐藏。
				if (MainForm != null)
				{
					MainForm.ShowPopForm(destForm);
				}
				else
				{
					destForm.ShowDialog();
					destForm.Close();
				}
			}
			else
			{
				Form mainForm = MainForm as Form;
				if (destForm.FormBorderStyle.ToString().StartsWith("Fixed"))
				{
					destForm.Show(mainForm);
				}
				else //如果定义为非弹出窗体，并且不固定大小,即为MDI窗体
				{
					if (mainForm.IsMdiContainer)
					{
						Add(moduleInfo.View); //在导航栏上显示窗体
						destForm.MdiParent = mainForm;
					}

					int width = Screen.PrimaryScreen.Bounds.Width - SystemInformation.BorderSize.Width * 2;
					int height = Screen.PrimaryScreen.Bounds.Height - SystemInformation.BorderSize.Height * 2 - SystemInformation.CaptionHeight - SystemInformation.MenuHeight;

					destForm.Size = new System.Drawing.Size(width, height);

					destForm.WindowState = FormWindowState.Maximized; //非弹出窗体且固定都自动最大化
					destForm.Show();
				}
			}

			return destForm;
		}

		private void Add(IBaseForm destForm)
		{
			if (TabNavManager.TabNav == null)
			{
				destForm.Show();
				destForm.BringToFront();
				return;
			}

			if (TabNavManager.ExistsForm(destForm)) //如果窗体已经在导航栏上存在了，那么激活窗体
			{
				TabNavManager.ActivateMdiForm(destForm);
			}
			else
			{
				TabNavManager.Add(destForm);

				destForm.Activated += new EventHandler(delegate(object sender, EventArgs e)
				{
					TabNavManager.ActivateMdiForm(destForm);
				});

				destForm.FormClosed += new FormClosedEventHandler(delegate(object sender, FormClosedEventArgs e)
				{
					TabNavManager.CloseMdiForm(destForm);
				});
			}
		}

		//向每个打开的模块（窗体）发送广播消息
		public bool SendBroadcast(string message, object param)
		{
			foreach (IBaseForm f in Application.OpenForms)
			{
				f.ReceiveBroadcast(message, param);
			}
			return true;
		}

		private bool HasPrivilege(ModuleInfo destModule, IBaseForm destForm)
		{
			//如果模块不显示在菜单中，或者是固定模块，那么不检查权限
			if (!destModule.Attribute.ShowInMenu || destModule.Attribute.Fix || !destModule.Attribute.Permission)
			{
				return true;
			}

			//如果是系统模块，那么系统管理员无条件可使用
			if (destModule.Attribute.SystemModule && ClientContext.User.IsAdmin)
			{
				return true;
			}

			//判断用户是否有调用方法的权限
			if (!PermissionManager.Instance.HasPermission(destModule, "运行"))
			{
				MessageBox.Show(string.Format("您没有 {0} 的运行权限，请与系统管理员联系！", destModule.Attribute.Name), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
				return false;
			}

			return true;
		}

	}
}


