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

using System;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Threading;
using System.Windows.Forms;
using Framework.BaseUI;
using Framework.Common;
using Framework.HandlerBase;
using Framework.RPC;
using Infrastructure.Components;

namespace Framework.MainUI
{
	/// <summary>
	/// 启动程序
	/// </summary>
	public static class ApplicationLoader
	{
		/// <summary>
		/// 系统已登录事件。
		/// </summary>
		public static event Action<IUser> SystemLogon;

		/// <summary>
		/// 系统已登出事件。
		/// </summary>
		public static event Action SystemLogout;

		/// <summary>
		/// 主窗体已显示事件。
		/// </summary>
		public static event Action MainFormShown;

		public static void RaiseMainFormShown()
		{
			if (MainFormShown != null)
			{
				MainFormShown();
			}
		}

		/// <summary>
		/// 应用程序的主入口点。同时只允许运行一个实例。
		/// </summary>
		public static bool Startup(string[] assemblies)
		{
			if (string.IsNullOrEmpty(MsgBox.Title))
			{
				MsgBox.Title = "系统提示";
			}
			return Startup(assemblies, true);
		}

		public static bool Startup(string[] assemblies, bool isLogin)
		{
			//所有未处理的错误，都会集中到此处处理。
			Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
			AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

			// 本地化DevExpress控件
			Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CHS");
			DevExpress.XtraEditors.Controls.Localizer.Active = new LocalizationEditorCHS();
			DevExpress.XtraGrid.Localization.GridLocalizer.Active = new LocalizationGridCHS();

			return Run(assemblies, isLogin);
		}

		private static bool Run(string[] assemblies, bool isLogin)
		{
			if (isLogin)
			{
				LoginForm loginForm = new LoginForm();
				if (loginForm.ShowDialog() == DialogResult.OK)
				{
					if (SystemLogon != null)
					{
						SystemLogon(ClientContext.User);
					}

					if (!UpgradeClient.Upgrade(loginForm.Account, loginForm.Password)) //登录成功之后检测升级。
					{
						return false;
					}
				}
				else
				{
					return false;
				}
			}

			ModuleParser.Instance.Analyse(assemblies);
			Form mainForm = new MainForm();
			mainForm.FormClosed += (_, __) =>
			{
				if (SystemLogout != null)
				{
					SystemLogout();
				}
			};

			HeartBeat();

			ModuleLoader.Instance.MainForm = (IMainForm)mainForm;
			Application.Run(mainForm);

			return false;
		}

		private static readonly System.Timers.Timer timer = new System.Timers.Timer();

		private static void HeartBeat()
		{
			HeartbeatResult result = Rpc.Create<SessionHandler>().Heartbeat2();
			ClientContext.Now = result.Now;

			timer.Interval = 1000 * 60; //每分钟发送一次心跳。
			timer.Elapsed += (s, e) =>
			{
				HeartbeatResult r = Rpc.Create<SessionHandler>().Heartbeat2();
				ClientContext.Now = r.Now;
			};
			timer.Start();
		}

		#region - Process Exception -

		static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
		{
			ClientContext.SetSessionData(); //服务器抛出异常后，CallContext的数据会自动清空，所以重新补上。

			if (e.ExceptionObject is Exception)
			{
				if (e.ExceptionObject is SocketException)
				{
					HandleSocketException(e.ExceptionObject as SocketException);
				}
				else
				{
					Exception ex = e.ExceptionObject as Exception;
					ex = ex.InnerException == null ? ex : ex.InnerException;
					SaveException(ex);
					MsgBox.Warning(ex.Message);
				}
			}
			else
			{
				MsgBox.Warning(e.ExceptionObject.ToString());
			}
		}

		static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
		{
			ClientContext.SetSessionData(); //服务器抛出异常后，CallContext的数据会自动清空，所以重新补上。

			SaveException(e.Exception);

			//if (e.Exception is EntityCommandExecutionException)
			//{
			//	if (e.Exception.InnerException is SqlException)
			//	{
			//		MsgBox.Error("SQL错误：" + e.Exception.InnerException.Message);
			//		return;
			//	}
			//}

			string msg = e.Exception.Message;

			if (e.Exception is SerializationException || e.Exception.InnerException is SerializationException)
			{
				if (e.Exception.Message.Contains("Framework.DomainBase.DB"))
				{
					msg = "";
				}
			}
			else
			{
				if (ClientContext.User != null && ClientContext.User.IsAdmin)
				{
					msg = e.Exception.InnerException == null ? e.Exception.ToString() : e.Exception.InnerException.ToString();

				}
				else
				{
					msg = e.Exception.InnerException == null ? e.Exception.Message : e.Exception.InnerException.Message;
				}
			}

			MsgBox.Error(msg);
		}

		private static void HandleSocketException(SocketException socketException)
		{
			SaveException(socketException);
			if (socketException.ErrorCode == (int)SocketError.ConnectionRefused) //10061
			{
				MsgBox.Error("与服务器的连接被中断，请与系统管理员联系！");
			}
			else if (socketException.ErrorCode == (int)SocketError.ConnectionReset) //10054
			{
				MsgBox.Error("服务器被强制关闭，请与系统管理员联系！");
			}
		}

		private static void SaveException(Exception ex)
		{
			if (ex == null)
			{
				return;
			}

			try
			{
				string path = Path.Combine(Application.StartupPath, "Error.log");
				File.AppendAllText(path, "\r\n========== " + ClientContext.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ==========\r\n" + ex.Message + "\r\n" + ex.StackTrace);
			}
			catch
			{
			}
		}

		#endregion
	}
}
