using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Media;
using PCL.Core.App;
using PCL.Core.Logging;
using PCL.Core.App.Localization;

namespace PCL;

public static class ModWatcher
{
    // 对全体的监视
    public static List<Watcher> mcWatcherList = new();
    private static bool isWatcherRunning;
    public static bool hasRunningMinecraft;

    private static void WatcherStateChanged()
    {
        var isRunning = false;
        var triggerLauncherShutdown = true;
        foreach (var Watcher in mcWatcherList)
        {
            if (Watcher.State == Watcher.MinecraftState.Loading || Watcher.State == Watcher.MinecraftState.Running)
            {
                isRunning = true;
                break;
            }

            if (Watcher.State == Watcher.MinecraftState.Crashed || Watcher.State == Watcher.MinecraftState.Canceled)
                triggerLauncherShutdown = false;
        }

        if (isWatcherRunning == isRunning)
            return;
        isWatcherRunning = isRunning;
        if (isWatcherRunning)
            MinecraftStart();
        else
            MinecraftStop(triggerLauncherShutdown);
    }

    private static void MinecraftStart()
    {
        ModLaunch.McLaunchLog("[全局] 出现运行中的 Minecraft");
        hasRunningMinecraft = true;
        ModMain.frmMain.BtnExtraShutdown.ShowRefresh();
    }

    private static void MinecraftStop(bool triggerLauncherShutdown)
    {
        ModLaunch.McLaunchLog("[全局] 已无运行中的 Minecraft");
        hasRunningMinecraft = false;
        ModMain.frmMain.BtnExtraShutdown.ShowRefresh();
        // 音乐播放
        if (Config.Preference.Music.StopInGame)
            ModBase.RunInUi(() =>
            {
                if (ModMusic.MusicResume()) ModBase.Log("[Music] 已根据设置，在结束后开始音乐播放");
            });
        else if (Config.Preference.Music.StartInGame)
            ModBase.RunInUi(() =>
            {
                if (ModMusic.MusicPause()) ModBase.Log("[Music] 已根据设置，在结束后暂停音乐播放");
            });
        // 开始视频背景播放
        ModVideoBack.IsGaming = false;
        ModVideoBack.VideoPlay();
        // 启动器可见性
        switch (Config.Launch.LauncherVisibility)
        {
            case LauncherVisibility.HideAndExit:
                // 直接关闭
                if (triggerLauncherShutdown)
                    ModBase.RunInUi(() => ModMain.frmMain.EndProgram(false));
                else
                    ModBase.RunInUi(() => ModMain.frmMain.Hidden = false);
                break;
            case LauncherVisibility.HideAndReopen:
                // 恢复
                ModBase.RunInUi(() => ModMain.frmMain.Hidden = false);
                break;
        }
    }

    private static GameLogLevel GetLevel(string line, GameLogLevel lastLevel)
    {
        Func<string, SolidColorBrush> getColorBrush =
            name => (SolidColorBrush)System.Windows.Application.Current.Resources[name];
        var starting = line.Split(": ")[0];
        if (starting.ContainsF("FATAL"))
            return GameLogLevel.Fatal;
        if (starting.ContainsF("ERROR"))
            return GameLogLevel.Error;
        if (starting.ContainsF("WARN"))
            return GameLogLevel.Warn;
        if (starting.ContainsF("INFO"))
            return GameLogLevel.Info;
        if (starting.ContainsF("DEBUG"))
            return GameLogLevel.Debug;
        if (line.StartsWithF("Exception in thread \""))
            return GameLogLevel.Error;
        if ((line.ContainsF("Exception") || line.ContainsF("Realms authentication error with message ")) &&
            lastLevel >= GameLogLevel.Warn)
            return lastLevel;
        if (line.StartsWithF("	at ") && lastLevel >= GameLogLevel.Warn)
            return lastLevel;
        return GameLogLevel.Info;
    }

    private static SolidColorBrush GetColor(GameLogLevel level)
    {
        Func<string, SolidColorBrush> getColorBrush =
            name => (SolidColorBrush)System.Windows.Application.Current.Resources[name];
        switch (level)
        {
            case GameLogLevel.Debug:
            {
                return getColorBrush("ColorBrushDebug");
            }
            case GameLogLevel.Info:
            {
                getColorBrush(ThemeManager.IsDarkMode ? "ColorBrushInfoDark" : "ColorBrushInfo");
                break;
            }
            case GameLogLevel.Warn:
            {
                return getColorBrush("ColorBrushWarn");
            }
            case GameLogLevel.Error:
            {
                return getColorBrush("ColorBrushError");
            }
            case GameLogLevel.Fatal:
            {
                return getColorBrush("ColorBrushFatal");
            }
        }

        return getColorBrush(ThemeManager.IsDarkMode ? "ColorBrushInfoDark" : "ColorBrushInfo");
    }

    // 实时日志处理
    public class LogOutputEventArgs : EventArgs
    {
        public SolidColorBrush color;
        public string logText;

        public LogOutputEventArgs(string logText, SolidColorBrush color)
        {
            this.logText = logText;
            this.color = color;
        }
    }

    private enum GameLogLevel
    {
        Debug = 0,
        Info = 1,
        Warn = 2,
        Error = 3,
        Fatal = 4
    }

    // 对单个进程的监视
    public class Watcher
    {
        public delegate void GameExitEventHandler();

        public delegate void LogOutputEventHandler(Watcher sender, LogOutputEventArgs e);

        public enum MinecraftState
        {
            Loading,
            Running,
            Crashed,
            Ended,
            Canceled
        }

        private readonly int pid;

        /// <summary>
        ///     是否处理实时日志。
        /// </summary>
        private readonly bool realTime;

        private readonly object waitingLogLock = new();
        public uint countDebug;
        public uint countError;
        public uint countFatal;
        public uint countInfo;
        public uint countWarn;

        /// <summary>
        ///     游戏的所有日志输出，只有处理实时日志的情况下才会记录。
        /// </summary>
        public List<string> fullLog = new();

        // 初始化
        public Process gameProcess;

        // 窗口检查
        private bool isWindowAppeared;

        /// <summary>
        ///     窗口检查是否已经完成。这不一定代表着找到了窗口（如果没有找到，IsWindowAppeared 仍为 False）。
        /// </summary>
        private bool isWindowFinished;

        public string jStackPath;

        /// <summary>
        ///     上一行日志级别。
        /// </summary>
        private GameLogLevel lastLevel = GameLogLevel.Info;

        public Queue<string> latestLog = new();
        public ModLoader.LoaderTask<Process, int> loader;

        // 进度更新
        private int logProgress;
        public McInstance version;

        // 日志
        public List<string> waitingLog = new(1000);
        private nint windowHandle;
        private string windowTitle = "";

        public Watcher(ModLoader.LoaderTask<Process, int> loader, McInstance version, string windowTitle,
            string jStackPath, bool outputRealTime = false)
        {
            this.loader = loader;
            this.version = version;
            this.windowTitle = windowTitle;
            realTime = outputRealTime;
            pid = loader.input.Id;
            this.jStackPath = jStackPath;

            WatcherLog(Lang.Text("Watcher.Start"));
            if (string.IsNullOrWhiteSpace(windowTitle))
                WatcherLog("要求窗口标题：" + windowTitle);

            // 更改列表
            var newWatcherList = new List<Watcher>();
            foreach (var Watch in mcWatcherList)
            {
                if (Watch.State == MinecraftState.Crashed || Watch.State == MinecraftState.Ended ||
                    Watch.State == MinecraftState.Canceled)
                    continue;
                newWatcherList.Add(Watch);
            }

            newWatcherList.Add(this);
            mcWatcherList = newWatcherList;
            WatcherStateChanged();

            // 初始化进程与日志读取
            gameProcess = loader.input;
            gameProcess.BeginOutputReadLine();
            gameProcess.BeginErrorReadLine();
            gameProcess.OutputDataReceived += LogReceived;
            gameProcess.ErrorDataReceived += LogReceived;

            // 初始化时钟
            // 设置窗口标题

            ModBase.RunInNewThread(() =>
            {
                try
                {
                    while (State != MinecraftState.Ended && State != MinecraftState.Crashed &&
                           State != MinecraftState.Canceled && loader.State != ModBase.LoadState.Aborted)
                    {
                        TimerWindow();
                        TimerLog();
                        if (!string.IsNullOrWhiteSpace(windowTitle))
                            for (var i = 1; i <= 3; i++)
                            {
                                if (State == MinecraftState.Running && !gameProcess.HasExited)
                                {
                                    var realTitle = windowTitle.Replace("{date}", Lang.Date(DateTime.Now, "d"))
                                        .Replace("{time}", Lang.Date(DateTime.Now, "T"));
                                    SetWindowText(windowHandle, realTitle);
                                }

                                Thread.Sleep(64);
                            }

                        Thread.Sleep(10);
                    }

                    WatcherLog(Lang.Text("Watcher.Exited"));
                }
                catch (Exception ex)
                {
                    ModBase.Log(
                        ex,
                        "Minecraft 日志监控主循环出错",
                        ModBase.LogLevel.Feedback,
                        userSummary: Lang.Text("Minecraft.Launch.Error.WatcherOperationFailed"));
                    State = MinecraftState.Ended;
                }
            }, "Minecraft Watcher PID " + pid);
        }

        public MinecraftState State
        {
            get => field;
            set
            {
                if (field == value)
                    return;
                field = value;
                WatcherStateChanged();
            }
        } = MinecraftState.Loading;

        /// <summary>
        ///     是否处理实时日志。
        /// </summary>
        public bool RealTimeLog => realTime;

        // 状态
        /// <summary>
        ///     游戏退出时触发。
        /// </summary>
        public event GameExitEventHandler? GameExit;

        private void LogReceived(object sender, DataReceivedEventArgs e)
        {
            lock (waitingLogLock)
            {
                waitingLog.Add(e.Data);
            }

            if (realTime)
            {
                LogRealTime(e.Data, ref lastLevel);
                if (e.Data is not null)
                    fullLog.Add(e.Data);
            }
        }

        /// <summary>
        ///     触发日志改变事件，并统计日志行数。
        /// </summary>
        private void LogRealTime(string line, ref GameLogLevel level)
        {
            if (line is null)
                return; // 杀游戏进程时有概率传 null
            level = line.StartsWithF("	at ") || line.StartsWithF("Caused by: ") || line.StartsWithF("	... ")
                ? level
                : GetLevel(line, level);

            // “	... 4 more”
            var color = GetColor(level);
            switch (level)
            {
                case GameLogLevel.Debug:
                {
                    countDebug = (uint)(countDebug + 1L);
                    break;
                }
                case GameLogLevel.Info:
                {
                    countInfo = (uint)(countInfo + 1L);
                    break;
                }
                case GameLogLevel.Warn:
                {
                    countWarn = (uint)(countWarn + 1L);
                    break;
                }
                case GameLogLevel.Error:
                {
                    countError = (uint)(countError + 1L);
                    break;
                }
                case GameLogLevel.Fatal:
                {
                    countFatal = (uint)(countFatal + 1L);
                    break;
                }
            }

            LogOutput?.Invoke(this, new LogOutputEventArgs(line, color));
        }

        /// <summary>
        ///     有新的日志输出，日志计数器发生改变时触发。
        /// </summary>
        public event LogOutputEventHandler? LogOutput;

        private void TimerLog()
        {
            try
            {
                // 输出文本
                var copyed = new List<string>();
                lock (waitingLogLock)
                {
                    if (!waitingLog.Any())
                        return;
                    copyed = waitingLog;
                    waitingLog = new List<string>(1000);
                }

                foreach (var Str in copyed)
                    GameLog(Str);
                if (State == MinecraftState.Loading)
                    ProgressUpdate();
                // 游戏退出检查
                if (gameProcess.HasExited)
                {
                    WatcherLog(Lang.Text("Watcher.ProcessExited", gameProcess.ExitCode));
                    // 实时日志输出
                    if (realTime)
                    {
                        var arglevel = GameLogLevel.Info;
                        LogRealTime(Lang.Text("Watcher.ProcessExited", gameProcess.ExitCode), ref arglevel);
                    }

                    GameExit?.Invoke();
                    // If Process.ExitCode = 1 Then
                    // '返回值为 1，考虑是任务管理器结束
                    // WatcherLog("Minecraft 返回值为 1，考虑为任务管理器结束") '并不，崩了照样是 1
                    // State = MinecraftState.Ended
                    // Else
                    if (State == MinecraftState.Loading)
                    {
                        // 窗口未出现
                        WatcherLog(Lang.Text("Watcher.Crash.Suspected"));
                        Crashed();
                    }
                    else if (gameProcess.ExitCode != 0 && State == MinecraftState.Running &&
                             version.releaseTime.Year >= 2012)
                    {
                        // 返回值不为 0 且未结束
                        WatcherLog(Lang.Text("Watcher.Crash.AbnormalExit"));
                        Crashed();
                    }
                    else if (State != MinecraftState.Crashed)
                    {
                        // 正常关闭
                        State = MinecraftState.Ended;
                    }
                }
            }
            catch (Exception ex)
            {
                ModBase.Log(
                    ex,
                    "输出 Minecraft 日志失败",
                    ModBase.LogLevel.Feedback,
                    userSummary: Lang.Text("Minecraft.Launch.Error.WatcherOperationFailed"));
            }
        }

        private void GameLog(string text)
        {
            // 预处理
            if (text is null)
                return;
            text = text.Replace("\r\n", "\r").Replace("\n", "\r")
                .Replace("\r", "\r\n");
            // If Text.Contains("�����") Then Hint("检测到错误的日志编码：" & Text)
            // 加入预存储
            latestLog.Enqueue(text);
            if (latestLog.Count >= 501)
                latestLog.Dequeue();
            // 进度处理
            if (logProgress < 1)
            {
                WatcherLog(Lang.Text("Watcher.Progress.LogAppeared"));
                logProgress = 1;
            } // 可能第一句就是后面需要判断的 Log（重现：启动 1.15.2 原版）

            if (logProgress < 2 && text.Contains("Setting user:"))
            {
                WatcherLog(Lang.Text("Watcher.Progress.UserSet")); // 仅确保支持 Minecraft 1.7+
                logProgress = 2;
            }
            else if (logProgress < 3 && text.ContainsF("lwjgl version", true))
            {
                WatcherLog(Lang.Text("Watcher.Progress.LwjglConfirmed"));
                logProgress = 3;
            }
            else if (logProgress < 4 &&
                     (text.Contains("OpenAL initialized") || text.Contains("Starting up SoundSystem")))
            {
                WatcherLog(Lang.Text("Watcher.Progress.OpenAlLoaded")); // 仅确保支持 Minecraft 1.7+
                logProgress = 4;
            }
            else if (logProgress < 5 &&
                     ((text.Contains("Created") && text.Contains("textures") && text.Contains("-atlas")) ||
                      text.Contains("Found animation info")))
            {
                WatcherLog(Lang.Text("Watcher.Progress.TexturesLoaded")); // 仅确保支持 Minecraft 1.7+
                logProgress = 5;
            }

            // 输出日志
            // Log(Text)
            // 关闭与崩溃检测
            if (!text.Contains("[CHAT]"))
            {
                if (text.Contains("Someone is closing me!") ||
                    text.Contains("Restarting Minecraft with command")) // #1258
                {
                    WatcherLog(Lang.Text("Watcher.Log.CloseDetected", text));
                    State = MinecraftState.Ended;
                }
                else if (text.Contains("Crash report saved to") ||
                         text.Contains("This crash report has been saved to:"))
                {
                    // Text.Contains("Minecraft ran into a problem! Report saved to:") Then
                    // Minecraft 崩溃，忽略 VanillaFix
                    WatcherLog(Lang.Text("Watcher.Log.CrashDetected", text));
                    Crashed();
                }
                else if (text.Contains("Could not save crash report to"))
                {
                    WatcherLog(Lang.Text("Watcher.Log.CrashDetected", text));
                    Crashed();
                }
                else if (text.Contains("/ERROR]: Unable to launch") ||
                         text.Contains("An exception was thrown, the game will display an error screen and halt."))
                {
                    WatcherLog(Lang.Text("Watcher.Log.CrashDetected", text));
                    Crashed();
                }
            }
        }

        private void WatcherLog(string text)
        {
            ModLaunch.McLaunchLog("[" + pid + "] " + text);
        }

        private void ProgressUpdate()
        {
            double currentProgress;
            if (isWindowAppeared || logProgress >= 4)
            {
                currentProgress = 0.95d;
                WatcherLog(Lang.Text("Watcher.LoadComplete"));
                State = MinecraftState.Running;
            }
            else
            {
                currentProgress = Math.Min(logProgress, 3) / 3d * 0.9d;
            }

            loader.Progress = currentProgress;
        }

        private void TimerWindow()
        {
            try
            {
                if (gameProcess.HasExited)
                    return;
                if (isWindowFinished)
                    return;
                // 获取全部窗口，检查是否有新增的
                KeyValuePair<nint, string>? minecraftWindow = default;
                try
                {
                    minecraftWindow = TryGetMinecraftWindow();
                }
                catch (Win32Exception ex)
                {
                    // 拒绝访问（#1062）
                    ModBase.Log(
                        ex,
                        Lang.Text("Watcher.SecurityBlocked"),
                        ModBase.LogLevel.Hint,
                        userSummary: Lang.Text("Watcher.SecurityBlocked"));
                    isWindowFinished = true;
                }

                if (minecraftWindow is null)
                    return;
                var minecraftWindowName = minecraftWindow.Value.Value;
                var minecraftWindowHandle = minecraftWindow.Value.Key;
                // 已找到窗口
                if (!minecraftWindowName.StartsWithF("FML") && !minecraftWindowName.StartsWithF("Quilt Loader"))
                {
                    // 已找到 Minecraft 窗口
                    windowHandle = minecraftWindowHandle;
                    WatcherLog(Lang.Text("Watcher.WindowLoaded", minecraftWindowName, minecraftWindowHandle.ToInt64()));
                    isWindowFinished = true;
                    // 最大化
                    if (Config.Launch.GameWindowMode == GameWindowSizeMode.Maximized)
                        // 如果最大化导致屏幕渲染大小不对，那是 MC 的 Bug，不是我的 Bug
                        // ……虽然我很想这样说，但总有人反馈，算了
                        ModBase.RunInNewThread(() =>
                        {
                            try
                            {
                                Thread.Sleep(2000);
                                ShowWindow(windowHandle, 3U);
                                 WatcherLog(Lang.Text("Watcher.WindowMaximized", minecraftWindowHandle.ToInt64()));
                            }
                            catch (Exception ex)
                            {
                                ModBase.Log(ex, "最大化 Minecraft 窗口时出现错误");
                            }
                        }, "MinecraftWindowMaximize");
                }
                else if (!isWindowAppeared)
                {
                    // 已找到 FML 窗口
                    WatcherLog(Lang.Text("Watcher.FmlWindowLoaded", minecraftWindowName, minecraftWindowHandle.ToInt64()));
                }

                isWindowAppeared = true;
            }
            catch (Exception ex)
            {
                ModBase.Log(
                    ex,
                    "检查 Minecraft 窗口失败",
                    ModBase.LogLevel.Feedback,
                    userSummary: Lang.Text("Minecraft.Launch.Error.WatcherOperationFailed"));
            }
        }

        /// <summary>
        ///     获取可能是当前进程对应的 Minecraft 窗口的句柄和标题。
        ///     Nothing 代表未找到。
        /// </summary>
        private KeyValuePair<nint, string>? TryGetMinecraftWindow()
        {
            KeyValuePair<nint, string>? tryGetMinecraftWindowRet = default;
            tryGetMinecraftWindowRet = default;
            EnumWindows((hwnd, lParam) =>
            {
                if (tryGetMinecraftWindowRet is not null)
                    return false; // 找到后停止枚举

                var str = new StringBuilder(512);
                GetClassName(hwnd, str, str.Capacity);
                var className = str.ToString();

                if (!(className == "GLFW30" || className == "LWJGL" || className == "SunAwtFrame"))
                    return true;

                // 获取窗口标题名
                str = new StringBuilder(512);
                GetWindowText(hwnd, str, str.Capacity);
                var windowText = str.ToString();

                // 部分版本会搞个 GLFW message window 出来所以得反选
                if (!(windowText.StartsWithF("FML") ||
                      (windowText != "PopupMessageWindow" && !windowText.StartsWithF("GLFW"))))
                    return true;

                // 获取窗口关联的进程
                var processId = default(int);
                GetWindowThreadProcessId(hwnd, ref processId);
                try
                {
                    if (processId != gameProcess.Id)
                        return true;
                }
                catch (Exception ex)
                {
                    return true;
                }

                // 找到目标，赋值并停止枚举
                tryGetMinecraftWindowRet = new KeyValuePair<nint, string>(hwnd, windowText);
                return false;
            }, nint.Zero);
            return tryGetMinecraftWindowRet;
        }

        [DllImport("user32")]
        private static extern bool EnumWindows(EnumWindowsSub lpEnumFunc, nint lParam);

        [DllImport("user32", EntryPoint = "GetClassNameW", CharSet = CharSet.Unicode)]
        private static extern int GetClassName(nint hWnd, StringBuilder lpClassName, int nMaxCount);

        [DllImport("user32", EntryPoint = "GetWindowTextW", CharSet = CharSet.Unicode)]
        private static extern int GetWindowText(nint hWnd, StringBuilder lpString, int nMaxCount);

        [DllImport("user32", EntryPoint = "SetWindowTextW", CharSet = CharSet.Unicode)]
        private static extern bool SetWindowText(nint hWnd, string lpString);

        [DllImport("user32")]
        private static extern bool ShowWindow(nint hWnd, uint cmdWindow);

        [DllImport("user32")]
        private static extern int GetWindowThreadProcessId(nint hWnd, ref int lpdwProcessId);

        // 崩溃处理
        private void Crashed()
        {
            if (State is MinecraftState.Crashed or MinecraftState.Ended)
                return;
            State = MinecraftState.Crashed;
            // 崩溃分析
            if (!Config.Launch.DisableCrashAnalysis)
            {
                WatcherLog(Lang.Text("Watcher.Crash.Detected"));
                HintService.Hint(Lang.Text("Watcher.Crash.Hint"));

                ModBase.FeedbackInfo();
                ModBase.RunInNewThread(() =>
                {
                    try
                    {
                        Thread.Sleep(2000);
                        WatcherLog(Lang.Text("Watcher.Crash.AnalysisStart"));
                        var analyzer = new CrashAnalyzer(pid);
                        analyzer.Collect(version.PathIndie, latestLog.ToList());
                        analyzer.Prepare();
                        analyzer.Analyze(version);
                        analyzer.Output(
                            false,
                            [
                                version.PathInstance + version.Name + ".json",
                                LogWrapper.CurrentLogger.CurrentLogFiles.Last(),
                                ModBase.exePath + @"PCL\LatestLaunch.bat"
                            ]);
                    }
                    catch (Exception ex)
                    {
                        ModBase.Log(
                            ex,
                            "崩溃分析失败",
                            ModBase.LogLevel.Feedback,
                            userSummary: Lang.Text("Crash.Analysis.Error.Failed"));
                    }
                }, "Crash Analyzer");
            }
            else
            {
                WatcherLog(Lang.Text("Watcher.Crash.DetectedDisabled"));
            }
        }

        // 强制关闭
        public bool CheckAlive(Process p)
        {
            if (!p.HasExited)
                return true;
            var exists = Array.Exists(Process.GetProcesses(), item => item.Id == p.Id);
            if (exists)
                return true;
            return false;
        }

        public void Kill()
        {
            State = MinecraftState.Canceled;
            ModBase.RunInNewThread(() =>
            {
                WatcherLog(Lang.Text("Watcher.Kill.Attempt"));
                try
                {
                    if (CheckAlive(gameProcess))
                        gameProcess.Kill();
                    gameProcess.WaitForExit(5000);
                    if (CheckAlive(gameProcess))
                    {
                        WatcherLog(Lang.Text("Watcher.Kill.TaskkillAttempt"));
                        var taskkillInfo = new ProcessStartInfo
                        {
                            FileName = "taskkill.exe",
                            Arguments = $"/PID {gameProcess.Id} /F /T",
                            RedirectStandardOutput = true,
                            UseShellExecute = false
                        };
                        var taskkillProcess = Process.Start(taskkillInfo);
                        var output = taskkillProcess.StandardOutput.ReadToEnd();
                        WatcherLog(Lang.Text("Watcher.Kill.TaskkillResult", output));
                        gameProcess.WaitForExit(5000);
                        if (CheckAlive(gameProcess))
                        {
                            WatcherLog(Lang.Text("Watcher.Kill.Timeout"));
                            return;
                        }
                    }

                    WatcherLog(Lang.Text("Watcher.Kill.Success"));
                    if (realTime)
                    {
                        var arglevel = GameLogLevel.Info;
                        LogRealTime(Lang.Text("Watcher.ProcessExited", gameProcess.ExitCode), ref arglevel);
                    }

                    GameExit?.Invoke();
                }
                catch (Exception ex)
                {
                    ModBase.Log(
                        ex,
                        Lang.Text("Watcher.Kill.Failed"),
                        ModBase.LogLevel.Hint,
                        userSummary: Lang.Text("Watcher.Kill.Failed"));
                }
            });
        }

        // 导出运行栈
        public List<string> ExportStackDump(string savePath)
        {
            var dump = new List<string>();
            for (var i = 1; i <= 3; i++)
            {
                dump.Add(ModBase.ShellAndGetOutput(jStackPath, "-l -e " + gameProcess.Id));
                Thread.Sleep(3000);
            }

            return dump;
        }

        private delegate bool EnumWindowsSub(nint hwnd, nint lParam);
    }
}
