Imports PCL.Core.UI.Controls

Module ModStyle
    
    'Partly generated by claude-sonnet-4-20250514
    Public Class TimerRun
        Inherits Run
        Implements IDisposable

        Private _timer As Threading.DispatcherTimer = Nothing
        Private ReadOnly Property _isTimerRunning
            Get
                Return _timer IsNot Nothing AndAlso _timer.IsEnabled
            End Get
        End Property

        '定义依赖属性
        Public Shared ReadOnly UpdateIntervalProperty As DependencyProperty =
            DependencyProperty.Register(
            NameOf(UpdateInterval),
            GetType(TimeSpan),
            GetType(TimerRun),
            New PropertyMetadata(TimeSpan.FromSeconds(1)))
        '属性变化处理
        Protected Overrides Sub OnPropertyChanged(e As DependencyPropertyChangedEventArgs)
            MyBase.OnPropertyChanged(e)
            If e.Property Is UpdateIntervalProperty AndAlso _timer IsNot Nothing Then
                _timer.Interval = UpdateInterval
            End If
        End Sub

        'UpdateInterval 属性
        Public Property UpdateInterval As TimeSpan
            Get
                Return CType(GetValue(UpdateIntervalProperty), TimeSpan)
            End Get
            Set
                If Value > TimeSpan.Zero Then
                    SetValue(UpdateIntervalProperty, Value)
                End If
            End Set
        End Property

        Public Property AutoStart As Boolean

        Public Sub New(Optional interval As TimeSpan = Nothing, Optional autoStart As Boolean = False)
            _timer = New Threading.DispatcherTimer
            AddHandler _timer.Tick, AddressOf _timerTick
            Me.UpdateInterval = If(interval = Nothing, TimeSpan.FromSeconds(1), interval)
            Me.AutoStart = autoStart
        End Sub

        '定时器事件
        Public Delegate Sub TimerTickDelegate(sender As TimerRun)
        Public Event TimerTick As TimerTickDelegate

        Private Sub _timerTick(sender As Object, e As EventArgs)
            RaiseEvent TimerTick(Me)
        End Sub

        Private Sub OnLoaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
            If AutoStart Then StartTimer()
        End Sub

        Private Sub OnUnloaded(sender As Object, e As RoutedEventArgs) Handles Me.Unloaded
            StopTimer()
        End Sub

        Public Sub StartTimer()
            If Me.Dispatcher Is Nothing Then
                Log("[TimerRun] Dispatcher is null, unable to run", LogLevel.Critical)
                Return
            End If
            If Not _isTimerRunning Then _timer?.Start()
        End Sub

        Public Sub StopTimer()
            If _isTimerRunning Then _timer?.Stop()
        End Sub

        Private _isDisposed = False
        Public Sub Dispose() Implements IDisposable.Dispose
            If _isDisposed Then Return
            _isDisposed = True
            '资源释放
            RemoveHandler _timer.Tick, AddressOf _timerTick
            _timer?.Stop()
            _timer = Nothing
        End Sub

    End Class

    Public Class MinecraftFormatter
        Private Shared colorMap As New Dictionary(Of String, String) From {
            {"black", "0"},
            {"dark_blue", "1"},
            {"dark_green", "2"},
            {"dark_aqua", "3"},
            {"dark_red", "4"},
            {"dark_purple", "5"},
            {"gold", "6"},
            {"gray", "7"},
            {"dark_gray", "8"},
            {"blue", "9"},
            {"green", "a"},
            {"aqua", "b"},
            {"red", "c"},
            {"light_purple", "d"},
            {"yellow", "e"},
            {"white", "f"}
        }

        Private Shared ReadOnly random As New Random()
        Private Shared ReadOnly randomChars As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+-=[]{}|;:,.<>?/~"

        Public Shared Function ConvertToMinecraftFormat(data As JObject) As String
            Dim result As String = ""
            For Each item In data("extra")
                result += ProcessElement(item, New List(Of String)())
            Next
            Return result.Replace("§§", "§")
        End Function

        Private Shared Function ProcessElement(element As JObject, currentFormat As List(Of String)) As String
            Dim text As String = ""
            Dim formats As New List(Of String)(currentFormat)

            ' 处理格式
            If element.ContainsKey("bold") AndAlso element("bold").ToObject(Of Boolean) Then
                formats.Add("l")
            End If

            If element.ContainsKey("color") Then
                Dim color = element("color").ToString()
                Dim colorCode As String = "f"
                If colorMap.ContainsKey(color) Then
                    colorCode = colorMap(color)
                End If
                formats.Insert(0, colorCode) ' 颜色代码在前
            End If

            ' 应用格式
            If formats.Count > 0 Then
                text &= "§" & String.Join("§", formats)
            End If

            ' 添加文本内容
            If element.ContainsKey("text") Then
                text &= element("text").ToString()
            End If

            ' 处理子元素
            If element.ContainsKey("extra") Then
                For Each child In element("extra")
                    text &= ProcessElement(child, New List(Of String)(formats))
                Next
            End If

            Return text
        End Function

        ''' <summary>
        ''' Minecraft 文本格式化代码，用于显示不同颜色的文本
        ''' </summary>
        ''' <param name="text">要格式化的文本</param>
        ''' <param name="lab">控件</param>
        Public Shared Sub SetColorfulTextLab(text As String, lab As TextBlock, Optional isDarkMode As Boolean = True)
            If lab Is Nothing Then
                Log("[Style] SetColorfulTextLab: lab is null")
                Exit Sub
            End If
            lab.Inlines.Clear()

            Dim HasItalicProperty As Boolean = False '斜体
            Dim HasDeleteLineProperty As Boolean = False '删除线
            Dim HasStrickThroughProperty As Boolean = False '下划线
            Dim HasBlodProperty As Boolean = False '粗体
            Dim IsRandomText As Boolean = False '随机文本模式

            Dim color As String = If(isDarkMode, "#FFFFFF", "#888888")
            Dim isColorCode As Boolean = False
            Dim curRun As New TimerRun()
            lab.Inlines.Add(curRun)

            ' 用于存储需要随机化的文本段
            Dim randomTextRuns As New List(Of TimerRun)

            For Each c As Char In text
                If c = "§" Then '下一字符是格式化代码
                    isColorCode = True
                    Continue For
                End If
                If isColorCode Then
                    if Not MotdRenderer.TryGetColorFromCode(c, isDarkMode, color) Then
                        Select Case c
                            '格式化代码
                            Case "k", "K" '随机字符
                                IsRandomText = True
                                ' 开始新的Run用于随机文本
                                If Not String.IsNullOrEmpty(curRun.Text) Then
                                    curRun = New TimerRun()
                                    lab.Inlines.Add(curRun)
                                End If
                                curRun.AutoStart = True
                                randomTextRuns.Add(curRun)
                            Case "l" '粗体
                                HasBlodProperty = True
                            Case "o" '斜体
                                HasItalicProperty = True
                            Case "n" '下划线
                                HasStrickThroughProperty = True
                            Case "m" '删除线
                                HasDeleteLineProperty = True
                            Case "r" '重置
                                color = If(isDarkMode, "#FFFFFF", "#888888")
                                HasBlodProperty = False
                                HasItalicProperty = False
                                HasStrickThroughProperty = False
                                HasDeleteLineProperty = False
                                IsRandomText = False
                        End Select
                    End If

                    If Not String.IsNullOrEmpty(curRun.Text) AndAlso c <> "k" AndAlso c <> "K" Then '遇到格式代码但是有文本，重开一个Run
                        curRun = New TimerRun()
                        lab.Inlines.Add(curRun)
                    End If

                    curRun.Foreground = New SolidColorBrush(New MyColor(color))
                    curRun.FontWeight = If(HasBlodProperty, FontWeights.Bold, FontWeights.Normal)
                    curRun.FontStyle = If(HasItalicProperty, FontStyles.Italic, FontStyles.Normal)
                    curRun.TextDecorations = If(HasStrickThroughProperty, TextDecorations.Strikethrough, Nothing)
                    curRun.TextDecorations = If(HasDeleteLineProperty, TextDecorations.Underline, Nothing)
                Else
                    If IsRandomText Then
                        ' 随机模式下，添加随机字符
                        curRun.Text += randomChars(random.Next(randomChars.Length))
                    Else
                        curRun.Text += c
                    End If
                End If

                If isColorCode Then isColorCode = False
            Next

            ' 设置定时器来更新随机文本
            If randomTextRuns.Count > 0 Then
                For Each run In randomTextRuns
                    run.UpdateInterval = TimeSpan.FromMilliseconds(20)
                    AddHandler run.TimerTick, Sub(sender)
                        If Not String.IsNullOrEmpty(sender.Text) Then
                            Dim sb As New StringBuilder()
                            For i As Integer = 0 To sender.Text.Length - 1
                                sb.Append(randomChars(random.Next(randomChars.Length)))
                            Next
                            sender.Text = sb.ToString()
                        End If
                    End Sub
                Next
            End If
        End Sub
        
    End Class

End Module
