using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing.Design;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.UI.Design.WebControls;
using System.Windows.Forms;

namespace updater
{
    public partial class Form1 : BaseWinForm
    {
        private UpgradeInfo localVersion;
        private UpgradeInfo upgradeInfo;
        private OfficeStarter appStarter = new OfficeStarter();
        private static readonly string ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
        private static readonly string LocalVersionFilePath = ApplicationBase + Path.GetFileName("version.json");
        public static readonly string CONFIG_FILE = AppDomain.CurrentDomain.BaseDirectory + "app.json";

        private static readonly string UpgradeDir = ApplicationBase + "update\\";
        /*
         * gm-plugin.zverse.group       测试-开发
         * pre-gm-plugin.gachafun.com   预发布
         * gm-plugin.gachafun.com       正式发布
         */
#if DEBUG 
        private static string UpgradeInfoURI = "https://gm-plugin.gachafun.com/";
#else
        private static string UpgradeInfoURI = "https://gm-plugin.gachafun.com/";
#endif

        private string updateSource;

        private void InitAppByConfig()
        {
            try
            {
                if (File.Exists(CONFIG_FILE))
                {
                    string content = File.ReadAllText(CONFIG_FILE);
                    if (content == null || content.Length == 0) return;
                    AppConfig config = JsonConvert.DeserializeObject<AppConfig>(content);

                    // 插件网址
                    if (!string.IsNullOrEmpty(config.AppUrl))
                    {
                        UpgradeInfoURI = config.AppUrl;
                    }
                }
            }
            catch (Exception) { }
        }

        public Form1()
        {
            InitAppByConfig();
            InitializeComponent();

            string verTextFile = ApplicationBase + Path.GetFileName("app_version.txt");
            string appVersion = File.Exists(verTextFile) ? File.ReadAllText(verTextFile) : null;
            if (appVersion != null && appVersion.Length > 0)
            {
                this.localVersion = new UpgradeInfo() { Version = appVersion };
            }
            else
            {
                // 读取本地版本信息
                string source = File.Exists(LocalVersionFilePath) ? File.ReadAllText(LocalVersionFilePath) : null;
                if (source != null && source.Length > 0)
                {
                    UpgradeModel local = JsonConvert.DeserializeObject<UpgradeModel>(source);
                    this.localVersion = local.Info;
                }
            }
        }


        private void StartUpgrade()
        {
            string runningApp = CheckHostAppRunning();
            if (!string.IsNullOrEmpty(runningApp))
            {
                var result = MessageBox.Show(string.Format("检测到{0}正在运行中,是否强制关闭并继续执行更新操作", runningApp), "提示", MessageBoxButtons.OKCancel);
                if (result != DialogResult.OK)
                {
                    ButtonProcess.Visible = true;
                    ButtonProcess.Text = "继续更新";
                    return;
                }
                try
                {
                    OfficeKiller.KillWPSProcess();
                    OfficeKiller.KillWordProcess();
                }
                catch (Exception)
                {
                    MessageBox.Show("强制关闭失败,请手动关闭后重新执行更新操作");
                    ButtonProcess.Visible = true;
                    ButtonProcess.Text = "继续更新";
                    return;
                }
            }
            ButtonProcess.Visible = false;
            progressBar1.Visible = true;
            if (!Directory.Exists(UpgradeDir))
            {
                Directory.CreateDirectory(UpgradeDir);
            }
            string updateFileName = UpgradeDir + Path.GetFileName(upgradeInfo.DownloadUrl);
            // 判断是否已经存在升级包
            if (File.Exists(updateFileName))
            {
                ExtractUpdatePackage();
                return;
            }
            DownLoadFile(upgradeInfo.DownloadUrl, updateFileName);
        }

        public string CheckHostAppRunning()
        {
            Process[] array = Process.GetProcesses();
            var hasWPS = false;
            var hasWord = false;
            foreach (Process item2 in array)
            {
                if (item2.ProcessName.Equals("WINWORD"))
                {
                    hasWord = true;
                }
                else if (item2.ProcessName.Equals("wps"))
                {
                    hasWPS = true;
                }
            }
            if (hasWord && hasWPS) return "WPS与Word";
            if (hasWord) return "Word";
            if (hasWPS) return "WPS";
            return null;
        }

        private void LabelLog_Click(object sender, System.EventArgs e)
        {

        }

        public void CheckUpdate()
        {
            try
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
                                           | SecurityProtocolType.Tls
                                           | SecurityProtocolType.Tls11
                                           | SecurityProtocolType.Tls12;
                HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(UpgradeInfoURI + "api/v1/common/download/version");
                HttpWebResponse resp = (HttpWebResponse)httpWebRequest.GetResponse();
                // 获取响应内容
                if (resp.StatusCode == HttpStatusCode.OK)
                {
                    Stream receiveStream = resp.GetResponseStream();
                    StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
                    updateSource = readStream.ReadToEnd();
                    if (updateSource == null && updateSource.Length == 0)
                    {
                        LabelLog.Text = "获取更新信息失败，请稍后重试";
                        return;
                    }
                    resp.Close();
                    UpgradeModel update = JsonConvert.DeserializeObject<UpgradeModel>(updateSource);
                    ProcessUpdate(update);
                }
            }
            catch (Exception)
            {
                LabelLog.Text = "获取更新信息失败，请稍后重试";
            }
        }

        private void ProcessUpdate(UpgradeModel update)
        {
            this.upgradeInfo = update.Info;
            LabelLog.Text = update.Info.Message;

            if (localVersion == null || update.Info.NeedUpgrade(localVersion.Version))
            {
                //StartUpgrade();
                ButtonProcess.Text = "立即更新";
                ButtonProcess.Visible = true;
            }
            else
            {
                LabelLog.Text = "当前已是最新版本 V" + localVersion.Version;
                ButtonProcess.Text = "关闭";
                ButtonProcess.Visible = true;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Task t = new Task(() =>
            {
                ButtonProcess.Invoke(new Action(() =>
                {
                    CheckUpdate();
                }));
            });
            t.Start();
        }

        public void DownLoadFile(string url, string filename)
        {
            try
            {
                WebClient client = new WebClient();
                Uri uri = new Uri(url);

                client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressCallback);
                client.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCallback);
                client.DownloadFileAsync(uri, filename);
            }
            catch (Exception e)
            {
                ButtonProcess.Visible = true;
                ButtonProcess.Text = "重新更新";
                MessageBox.Show(e.Message);
            }
        }

        private void DownloadProgressCallback(object sender, DownloadProgressChangedEventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                progressBar1.Value = e.ProgressPercentage;
            }));
        }
        private void DownloadFileCallback(object sender, AsyncCompletedEventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                ExtractUpdatePackage();
            }));
        }

        private void StartInstallExe(string fileName)
        {
            // 启动更新程序
            Process.Start(fileName);
            this.Close();
        }

        private void ExtractUpdatePackage()
        {
            progressBar1.Value = 100;
            // 获取升级包路径
            string updateFileName = UpgradeDir + Path.GetFileName(upgradeInfo.DownloadUrl);
            try
            {
                if (updateFileName.EndsWith(".exe"))
                {
                    StartInstallExe(updateFileName);
                    return;
                }

                // 可以考虑备份旧文件
                //string destinationFolder = Path.Combine(applicationBase, "update\\old");
                //CopyDirectory(applicationBase, destinationFolder);
                //ZipFile.ExtractToDirectory(zipFilePath, applicationBase);

                using (ZipArchive zip = ZipFile.OpenRead(updateFileName))
                {
                    foreach (ZipArchiveEntry entry in zip.Entries)
                    {
                        // 采用覆盖模式进行解压
                        try
                        {
                            entry.ExtractToFile(Path.Combine(ApplicationBase, entry.FullName), true);
                        }
                        catch (Exception)
                        {

                        }
                    }
                }
                MessageBox.Show("更新完成, 您可以打开文档继续校对");
                // 保存最新版本日志
                try
                {
                    File.WriteAllText(LocalVersionFilePath, updateSource);
                }
                catch (Exception) { }
                appStarter.StartWPS();
                appStarter.StartMSOffice();
                this.Close();
            }
            catch (Exception)
            {
                try
                {
                    File.Delete(updateFileName);
                }catch { }
                var ret = MessageBox.Show("升级失败,是否需要手动执行更新?", "更新失败", MessageBoxButtons.YesNo);
                if (ret == DialogResult.Yes)
                {
                    Process.Start(upgradeInfo.DownloadUrl);
                    this.Close();
                }
                else
                {
                    ButtonProcess.Visible = true;
                    ButtonProcess.Text = "重新更新";
                }
            }
        }
        public static void CopyDirectory(string sourceFolder, string destinationFolder)
        {
            Directory.CreateDirectory(destinationFolder);
            string moduleName = Process.GetCurrentProcess().MainModule.ModuleName;
            FileSystemInfo[] fileSystemInfos = new DirectoryInfo(sourceFolder).GetFileSystemInfos();
            foreach (FileSystemInfo fileSystemInfo in fileSystemInfos)
            {
                if (fileSystemInfo is DirectoryInfo)
                {
                    if (fileSystemInfo.Name != "update" && fileSystemInfo.Name != "logs")
                    {
                        if (!Directory.Exists(destinationFolder + "\\" + fileSystemInfo.Name))
                        {
                            Directory.CreateDirectory(destinationFolder + "\\" + fileSystemInfo.Name);
                        }
                        CopyDirectory(fileSystemInfo.FullName, destinationFolder + "\\" + fileSystemInfo.Name);
                    }
                }
                else if (!fileSystemInfo.FullName.EndsWith(moduleName))
                {
                    File.Copy(fileSystemInfo.FullName, destinationFolder + "\\" + fileSystemInfo.Name, overwrite: true);
                }
            }
        }

        private void BtnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
            Application.Exit();
        }

        private void ButtonProcess_Click(object sender, EventArgs e)
        {
            switch (ButtonProcess.Text)
            {
                case "重新更新":
                case "立即更新":
                case "继续更新":
                    StartUpgrade();
                    break;
                case "关闭":
                    this.Close();
                    break;

            }
        }

        private void IconClose_Click(object sender, EventArgs e)
        {
            this.Close();
            Application.Exit();
        }

        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            HandleMouseDownAndMove();
        }
    }
}
