Imports System.IO
Imports PCL.Core.App
Imports PCL.Core.Utils
Imports PCL.Core.Utils.OS

Public Class Application

#If DEBUGRESERVED Then
    ''' <summary>
    ''' 用于开始程序时的一些测试。
    ''' </summary>
    Private Sub Test()
        Try
            ModDevelop.Start()
        Catch ex As Exception
            Log(ex, "开发者模式测试出错", LogLevel.Msgbox)
        End Try
    End Sub
#End If

    Public Sub New()
        Basics.VersionName = VersionBaseName
        Basics.VersionNumber = VersionCode
        '注册生命周期事件
        Lifecycle.When(LifecycleState.Loaded, AddressOf Application_Startup)
    End Sub

    '开始
    Private Sub Application_Startup() '(sender As Object, e As StartupEventArgs) Handles Me.Startup
        Try
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)
            '创建自定义跟踪监听器，用于检测是否存在 Binding 失败
            PresentationTraceSources.DataBindingSource.Listeners.Add(New BindingErrorTraceListener())
            PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Error
            SecretOnApplicationStart()
            '检查参数调用
            Dim args = Environment.GetCommandLineArgs.Skip(1).ToArray()
            If args.Length > 0 Then
                If args(0) = "--update" Then
                    '自动更新
                    UpdateReplace(args(1), args(2).Trim(""""), args(3).Trim(""""), args(4))
                    Environment.Exit(ProcessReturnValues.TaskDone)
                ElseIf args(0) = "--gpu" Then
                    '调整显卡设置
                    Try
                        SetGPUPreference(args(1).Trim(""""))
                        Environment.Exit(ProcessReturnValues.TaskDone)
                    Catch ex As Exception
                        Environment.Exit(ProcessReturnValues.Fail)
                    End Try
                ElseIf args(0).StartsWithF("--memory") Then
                    '内存优化
                    Dim Ram = KernelInterop.GetAvailablePhysicalMemoryBytes()
                    Try
                        PageOtherTest.MemoryOptimizeInternal(False)
                    Catch ex As Exception
                        MsgBox(ex.Message, MsgBoxStyle.Critical, "内存优化失败")
                        Environment.Exit(-1)
                    End Try
                    If KernelInterop.GetAvailablePhysicalMemoryBytes() < Ram Then '避免 ULong 相减出现负数
                        Environment.Exit(0)
                    Else
                        Environment.Exit((KernelInterop.GetAvailablePhysicalMemoryBytes() - Ram) / 1024) '返回清理的内存量（K）
                    End If
#If DEBUGRESERVED Then
                    '制作更新包
                ElseIf args(0) = "--edit1" Then
                    ExeEdit(args(1), True)
                    Environment.Exit(ProcessReturnValues.TaskDone)
                ElseIf args(0) = "--edit2" Then
                    ExeEdit(args(1), False)
                    Environment.Exit(ProcessReturnValues.TaskDone)
#End If
                End If
            End If
            '初始化文件结构
            Directory.CreateDirectory(ExePath & "PCL\Pictures")
            Directory.CreateDirectory(ExePath & "PCL\Musics")
            Try
                Directory.CreateDirectory(PathTemp)
                If Not CheckPermission(PathTemp) Then Throw New Exception("PCL 没有对 " & PathTemp & " 的访问权限")
            Catch ex As Exception
                If PathTemp = IO.Path.GetTempPath() & "PCL\" Then
                    MyMsgBox("PCL 无法访问缓存文件夹，可能导致程序出错或无法正常使用！" & vbCrLf & "错误原因：" & ex.ToString(), "缓存文件夹不可用")
                Else
                    MyMsgBox("手动设置的缓存文件夹不可用，PCL 将使用默认缓存文件夹。" & vbCrLf & "错误原因：" & ex.ToString(), "缓存文件夹不可用")
                    Setup.Set("SystemSystemCache", "")
                    PathTemp = IO.Path.GetTempPath() & "PCL\"
                End If
            End Try
            Directory.CreateDirectory(PathTemp & "Cache")
            Directory.CreateDirectory(PathTemp & "Download")
            Directory.CreateDirectory(PathAppdata)
#If False Then
            '检测单例
            Dim ShouldWaitForExit As Boolean = args.Length > 0 AndAlso args(0) = "--wait" '要求等待已有的 PCL 退出
            Dim WaitRetryCount As Integer = 0
WaitRetry:
            Dim WindowHwnd As IntPtr = FindWindow(Nothing, "Plain Craft Launcher Community Edition ")
            If WindowHwnd = IntPtr.Zero Then FindWindow(Nothing, "Plain Craft Launcher 2 Community Edition ")
            If WindowHwnd <> IntPtr.Zero Then
                If ShouldWaitForExit AndAlso WaitRetryCount < 20 Then '至多等待 10 秒
                    WaitRetryCount += 1
                    Thread.Sleep(500)
                    GoTo WaitRetry
                End If
                '将已有的 PCL 窗口拖出来
                ShowWindowToTop(WindowHwnd)
                '播放提示音并退出
                Beep()
                Environment.[Exit](ProcessReturnValues.Cancel)
            End If
#End If
            '设置 ToolTipService 默认值
            ToolTipService.InitialShowDelayProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(300))
            ToolTipService.BetweenShowDelayProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(400))
            ToolTipService.ShowDurationProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(9999999))
            ToolTipService.PlacementProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(Primitives.PlacementMode.Bottom))
            ToolTipService.HorizontalOffsetProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(8.0))
            ToolTipService.VerticalOffsetProperty.OverrideMetadata(GetType(DependencyObject), New FrameworkPropertyMetadata(4.0))
            '设置初始窗口
            If Setup.Get("UiLauncherLogo") Then
                FrmStart = New SplashScreen("Images\icon.ico")
                FrmStart.Show(False, True)
            End If
            '添加日志
            Log($"[Start] 程序版本：{VersionBaseName} (Channel: {VersionBranchName},Code: {VersionCode}{If(CommitHash = "", "", $"，#{CommitHash}")})")
            Log($"[Start] 识别码：{UniqueAddress}")
            Log($"[Start] 程序路径：{ExePathWithName}")
            Log($"[Start] 系统版本：{Environment.OSVersion.Version}, 架构：{Runtime.InteropServices.RuntimeInformation.OSArchitecture}")
            Log($"[Start] 系统编码：{Encoding.Default.HeaderName} ({Encoding.Default.CodePage}, GBK={IsGBKEncoding})")
            Log($"[Start] 管理员权限：{ProcessInterop.IsAdmin()}")
            '检测异常环境
            Dim problemList As New List(Of String)
            Dim currentOSVersion = KernelInterop.GetCurrentOSVersion()
            If currentOSVersion.Build < 17763 Then problemList.Add("- Windows 版本不满足推荐要求，推荐至少 Windows 10 1809，建议考虑升级 Windows 系统")
            If Is32BitSystem then problemList.Add("- 当前系统为 32 位，不受 PCL 和新版 Minecraft 支持，非常建议重装为 64 位系统后再进行游戏")
            If ExePath.Contains(IO.Path.GetTempPath()) OrElse ExePath.Contains("AppData\Local\Temp\") Then problemList.Add("- PCL 正在临时目录运行，请将 PCL 从压缩包中解压之后再使用，否则可能导致游戏存档或设置丢失")
            If ExePath.ContainsF("wechat_files", True) OrElse ExePath.ContainsF("WeChat Files", True) OrElse ExePath.ContainsF("Tencent Files", True) Then problemList.Add("- PCL 正在 QQ、微信、TIM 等社交软件的下载目录运行，请考虑移动到其他位置，否则可能导致游戏存档或设置丢失")
            If problemList.Count <> 0 Then
                MyMsgBox("PCL CE 在启动时检测到环境问题：" & vbCrLf & vbCrLf &
                         problemList.Join(vbCrLf) & vbCrLf & vbCrLf &
                         "不解决这些问题可能会导致部分功能无法正常工作……", "环境警告", "我知道了", IsWarn:=True)
            End If
            '设置初始化
            Setup.Load("SystemDebugMode")
            Setup.Load("SystemDebugAnim")
            Setup.Load("SystemHttpProxy")
            Setup.Load("SystemHttpProxyCustomUsername")
            Setup.Load("SystemHttpProxyType")
            Setup.Load("ToolDownloadThread")
            Setup.Load("ToolDownloadSpeed")
            Setup.Load("UiFont")
            Dim updateBranchCfg = Config.System.UpdateBranchConfig
            If updateBranchCfg.IsDefault() Then
                updateBranchCfg.SetValue(If(VersionBaseName.Contains("beta"), 1, 0))
            End If
            '删除旧日志
            For i = 1 To 5
                Dim oldLogFile = $"{ExePath}PCL\Log-CE{i}.log"
                If File.Exists(oldLogFile) Then File.Delete(oldLogFile)
            Next
            'Pipe RPC 初始化
            StartEchoPipe()
            '计时
            Log("[Start] 第一阶段加载用时：" & TimeUtils.GetTimeTick() - ApplicationStartTick & " ms")
            ApplicationStartTick = TimeUtils.GetTimeTick()
            '执行测试
#If DEBUGRESERVED Then
            Test()
#End If
            AniControlEnabled += 1
        Catch ex As Exception
            Dim FilePath As String = Nothing
            Try
                FilePath = ExePathWithName
            Catch
            End Try
            MsgBox(ex.ToString() & vbCrLf & "PCL 所在路径：" & If(String.IsNullOrEmpty(FilePath), "获取失败", FilePath), MsgBoxStyle.Critical, "PCL 初始化错误")
            FormMain.EndProgramForce(ProcessReturnValues.Exception)
        End Try
    End Sub

    '结束
    Private Sub Application_SessionEnding(sender As Object, e As SessionEndingCancelEventArgs) Handles Me.SessionEnding
        FrmMain.EndProgram(False)
    End Sub

#If False

    '异常
    Private Sub Application_DispatcherUnhandledException(sender As Object, e As DispatcherUnhandledExceptionEventArgs) Handles Me.DispatcherUnhandledException
        On Error Resume Next
        e.Handled = True
        If IsProgramEnded Then Return
        FeedbackInfo()
        Dim Detail As String = e.Exception.ToString()
        If Detail.Contains("System.Windows.Threading.Dispatcher.Invoke") OrElse Detail.Contains("MS.Internal.AppModel.ITaskbarList.HrInit") OrElse Detail.Contains("未能加载文件或程序集") Then ' “自动错误判断” 的结果分析
            OpenWebsite("https://get.dot.net/8")
            Log(e.Exception, "你的 .NET 桌面运行时版本过低或损坏，请下载并重新安装 .NET 8！", LogLevel.Critical, "运行环境错误")
        Else
            Log(e.Exception, "程序出现未知错误", LogLevel.Critical, "锟斤拷烫烫烫")
        End If
    End Sub

    Private Declare Function SetDllDirectory Lib "kernel32" Alias "SetDllDirectoryA" (lpPathName As String) As Boolean

#End If

    '切换窗口

    '控件模板事件
    Private Sub MyIconButton_Click(sender As Object, e As EventArgs)
    End Sub

    Public Shared ReadOnly ShowingTooltips As New List(Of Border)
    Private Sub TooltipLoaded(sender As Object, e As EventArgs)
        ShowingTooltips.Add(CType(sender, Border))
    End Sub
    Private Sub TooltipUnloaded(sender As Object, e As RoutedEventArgs)
        ShowingTooltips.Remove(CType(sender, Border))
    End Sub

    ' 自定义监听器类
    Public Class BindingErrorTraceListener
        Inherits TraceListener

        Public Overrides Sub Write(message As String)
            Log($"警告，检测到 Binding 失败：{message}")
        End Sub

        Public Overrides Sub WriteLine(message As String)
            Log($"警告，检测到 Binding 失败：{message}")
        End Sub
    End Class

End Class
