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

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace Framework.Upgrade
{
	internal static class ClientUpgrade
	{
		private static List<string> _FileList = new List<string>();

		/// <summary>
		/// args的参数：1.版本号；2：登录账号；3：登录密码；4：要启动的应用程序名。
		/// </summary>
		public static void Update(string[] args)
		{
			long versionNo = 0;
			string account = "";
			string password = "";
			string applicationName = "";
			string processName = "";

			//if (args.Length != 5)
			//{
			//	string str = "";
			//	foreach (string s in args)
			//	{
			//		if (str != "")
			//		{
			//			str = str + ",";
			//		}
			//		str = str + s;
			//	}

			//	MessageBox.Show("参数错误，退出升级！错误原因：参数个数不正确！\r\n" + str);
			//	return;
			//}

			try
			{
				versionNo = long.Parse(args[0]);
			}
			catch
			{
				MessageBox.Show("参数错误，退出升级！无法解析的版本号：" + args[0]);
				return;
			}

			if (args.Length >= 3)
			{
				applicationName = args[1];
				processName = args[2];
			}
			if (args.Length >= 5)
			{
				account = args[3];
				password = args[4];
			}

			CloseApplication(processName);

			string upgradePath = Application.StartupPath + "\\Upgrade\\"; //升级文件下载后存放在Upgrade目录下。

			Console.WriteLine("准备删除...");
			DeleteFile(upgradePath); //删除目录和文件。

			Console.WriteLine("准备移动...");
			MoveDir(upgradePath); //移动目录。

			//升级成功，保存升级信息。
			UpgradeConfig upgradeConfig = new UpgradeConfig()
			{
				VersionNo = versionNo,
				UpgradeTime = DateTime.Now,
				UpgradeFiles = _FileList.ToArray()
			};
			upgradeConfig.Save();

			//启动应用程序。
			MessageBox.Show(string.Format("升级完毕，系统已成功升级到{0}版本！", upgradeConfig.VersionNo), "系统升级", MessageBoxButtons.OK, MessageBoxIcon.Information);
			Application.ApplicationExit += delegate
			{
				Console.WriteLine(string.Format("准备启动主程序 {0} ...", applicationName));
				if (account != null)
				{
					Console.WriteLine(string.Format("正在启动主程序1 {0} ...", applicationName));

					try
					{
						Process.Start(applicationName, account + " " + password);
					}
					catch(Exception ex)
					{
						MessageBox.Show(ex.Message);
					}
				}
				else
				{
					Console.WriteLine(string.Format("正在启动主程序2 {0} ...", applicationName));
					Process.Start(applicationName);
				}
			};
			Application.Exit();
		}

		private static void CloseApplication(string processName)
		{
			//找到应用程序的进程，并关闭。
			Process[] processes = Process.GetProcessesByName(processName);
			if (processes != null && processes.Length > 0)
			{
				foreach (Process p in processes)
				{
					try
					{
						//p.Close(); 不能直接调用Close，某些情况下会无法关闭进程，原因待查。
						p.CloseMainWindow();
						p.WaitForExit(3000);
					}
					catch
					{
						Console.WriteLine("关闭进程{0}失败", processName);
					}
				}
			}
		}

		//_upgrade_delete_.lst 记录了要删除的文件名。
		private static void DeleteFile(string upgradePath)
		{
			string fileName = upgradePath + "_upgrade_delete_.lst";
			if (!File.Exists(fileName))
			{
				return;
			}

			foreach (string file in File.ReadAllLines(fileName))
			{
				string path = Path.Combine(Application.StartupPath, file);
				try
				{
					Console.WriteLine("准备删除文件(夹) {0}", path);
					if (File.Exists(path)) //如果是文件，
					{
						File.Delete(path);
						Console.WriteLine("已删除文件 {0}", path);
					}
					else if (Directory.Exists(path)) //否则是文件夹。
					{
						Directory.Delete(path, true); //注意，不能删除中文名称的文件夹。
						Console.WriteLine("已删除文件夹 {0}", path);
					}
					else
					{
						Console.WriteLine("未发现文件(夹)，删除失败");
					}
				}
				catch
				{
					Console.WriteLine();
					Console.WriteLine("文件(夹)删除失败 {0}", path);
				}
			}

			File.Delete(fileName);
		}

		static void MoveDir(string rootDir)
		{
			//1.移动文件
			MoveDir(rootDir, rootDir);
			//2.移动子目录
			string[] directories = Directory.GetDirectories(rootDir);
			foreach (string subDir in directories)
			{
				MoveDir(rootDir, subDir);
			}
		}

		static void MoveDir(string rootDir, string dir)
		{
			if (!Directory.Exists(dir))
			{
				Console.WriteLine("目录{0}不存在", dir);
				return;
			}

			string[] files = Directory.GetFiles(dir);
			Console.WriteLine("准备移动{0}下的文件（共{1}个）", dir, files.Length);
			for (int i = 0; i < files.Length; i++)
			{
				string source = files[i];
				Console.WriteLine(Path.GetFileName(source));
				if (Path.GetFileName(source) == "Framework.Upgrade.exe")
				{
					Console.WriteLine("忽略 " + source);
					continue;
				}

				Console.WriteLine("准备移动 " + source);

				string dest = Path.Combine(Application.StartupPath, source.Replace(rootDir, ""));

				string destDir = Path.GetDirectoryName(dest);
				if (!Directory.Exists(destDir))
				{
					Console.WriteLine("创建目录 " + destDir);
					Directory.CreateDirectory(destDir);
				}

				File.SetAttributes(source, FileAttributes.Normal);
				if (File.Exists(dest))
				{
					Console.WriteLine("清除文件 " + dest);
					File.SetAttributes(dest, FileAttributes.Normal);
					File.Delete(dest);
				}
				File.Move(source, dest);

				Console.WriteLine("移动成功 " + dest);
				Console.WriteLine();

				_FileList.Add(dest);
			}
		}

		static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
		{
			MessageBox.Show(((Exception)e.ExceptionObject).Message);
		}

		static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
		{
			MessageBox.Show(e.Exception.Message);
		}
	}
}
