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

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

namespace Framework.BaseUI
{
	public class ModuleLoader
	{
		private static ModuleLoader instance = new ModuleLoader();

		public static ModuleLoader Instance
		{
			get
			{
				return instance;
			}
		}

		private Dictionary<string, Assembly> asmList = new Dictionary<string, Assembly>();

		private ModuleLoader()
		{
		}

		public IMainForm MainForm
		{
			get;
			set;
		}

		public Type GetFormType(string dllName, string formClassName, object[] args)
		{
			Assembly asm = GetAssembly(dllName);
			Type formType = asm.GetType(formClassName, false);
			return formType;
		}

		public Assembly GetAssembly(string dllName)
		{
			Assembly asm = null;
			try
			{
				if (asmList.ContainsKey(dllName)) //如果Assembly已经装载过了，那么直接取出来使用
				{
					asm = asmList[dllName];
				}
				else
				{
					try
					{
						asm = Assembly.LoadFrom(dllName);
					}
					catch (Exception ex)
					{
#if DEBUG
						throw ex;
#endif
					}

					if (asm == null)
					{
						return null;
					}

					asmList.Add(dllName, asm); //缓存Assembly
				}
				return asm;
			}
			catch (Exception ex)
			{
				Debug.Print(ex.Message);
			}
			return null;
		}

		//<summary>
		//从DLL中装载窗体
		//</summary>
		//<param name="ModuleName">DLL文件名</param>
		//<param name="FormClassName">窗体类名（需要包含命名空间）</param>
		//<returns>返回窗体的引用对象</returns>
		public IBaseForm LoadForm(string dllName, string formClassName)
		{
			IBaseForm view = FindView(dllName, formClassName);
			if (view != null) //如果窗体已经建立，并缓存在列表中，那么直接返回缓存的窗体
			{
				return view;
			}

			object obj = null;

			Assembly asm = GetAssembly(dllName);
			if (asm == null)
			{
				return null;
			}

			try
			{
				Type formType = asm.GetType(formClassName, false);

				//如果需要在窗体建立的同时传入参数，并且在构造函数上有FormParam类型的参数，那么传入参数
				obj = asm.CreateInstance(formType.FullName);
			}
			catch (Exception ex)
			{
				if (ex.InnerException != null)
				{
					MessageBox.Show(ex.InnerException.Message + "\r\n\r\n" + ex.InnerException.StackTrace);
				}
				else
				{
					throw ex; //如果报告未找到构造函数，请增加一个有formParam参数的构造窗体
				}
			}

			view = obj as IBaseForm;
			if (view != null)
			{
				MainForm.FormList.Add(view);
				view.Disposed += new EventHandler(f_Disposed);
			}
			return view;
		}

		private void f_Disposed(object sender, EventArgs e)
		{
			IBaseForm f = sender as IBaseForm;
			if (f == null)
			{
				return;
			}
			if (f.Disposing)
			{
				int n = FormIndex(f);
				if (n > -1)
				{
					RemoveFrom(n);
				}
			}
		}

		//移除窗体
		public bool RemoveFrom(string moduleName, string formClassName)
		{
			int p = FormIndex(moduleName, formClassName);
			if (p != -1)
			{
				MainForm.FormList.RemoveAt(p);
			}
			return p != -1;
		}

		/// <summary>
		/// 根据窗体在FormList中的Index，删除窗体
		/// </summary>
		/// <param name="index"></param>
		private void RemoveFrom(int index)
		{
			MainForm.FormList.RemoveAt(index);
		}

		/// <summary>
		/// 窗体对象在FormList的位置，可以用此函数来判断Form是否已经装载过了
		/// </summary>
		/// <param name="ModuleName">DLL文件名</param>
		/// <param name="FormClassName">Form的类名</param>
		/// <returns>窗体对象在FormList中的索引，如果找不到则返回-1</returns>
		public int FormIndex(string moduleName, string formClassName)
		{
			for (int i = 0; i < MainForm.FormList.Count; i++)
			{
				IBaseForm view = MainForm.FormList[i];
				if (view.Text == moduleName && view.GetType().FullName == formClassName)
				{
					return i;
				}
			}
			return -1;
		}

		/// <summary>
		/// 窗体对象在FormList的位置，可以用此函数来判断Form是否已经装载过了
		/// </summary>
		/// <param name="view">窗体对象</param>
		/// <returns>窗体对象在FormList中的索引，如果找不到则返回-1</returns>
		public int FormIndex(IBaseForm view)
		{
			for (int i = 0; i < MainForm.FormList.Count; i++)
			{
				if (MainForm.FormList[i] == view)
				{
					return i;
				}
			}
			return -1;
		}

		private IBaseForm FindView(string moduleName, string formClassName)
		{
			for (int i = 0; i < MainForm.FormList.Count; i++)
			{
				IBaseForm view = MainForm.FormList[i];
				if (view.Text == moduleName && view.GetType().FullName == formClassName)
				{
					return view;
				}
			}
			return null;
		}
	}
}