Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Components
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Icons
Imports Nexamas.UI.Theming
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Values
Imports Nexamas.UI.Architecture
Imports SkiaSharp

Namespace Nexamas.UI.Rendering

    Partial Friend NotInheritable Class MASToastRenderer
        Private Shared Function WrapLines(text As String,
                                          paint As SKPaint,
                                          maxWidth As Single,
                                          maxLines As Integer) As List(Of String)

            Dim result As New List(Of String)()
            Dim s As String = If(text, String.Empty).Trim()

            If s.Length = 0 Then Return result

            If paint Is Nothing OrElse maxWidth <= 4.0F Then
                result.Add(s)
                Return result
            End If

            Dim limit As Integer = Math.Max(1, maxLines)
            Dim words As String() =
                s.Split(New Char() {" "c, ChrW(9), ChrW(10), ChrW(13)},
                        StringSplitOptions.RemoveEmptyEntries)

            If words.Length = 0 Then
                result.Add(s)
                Return result
            End If

            Dim current As String = String.Empty
            Dim measureSession As MASTextWidthMeasureSession = MASTextWidthMeasureSession.ForPaint(paint)

            For i As Integer = 0 To words.Length - 1
                Dim w As String = words(i)

                Dim candidate As String =
                    If(current.Length = 0, w, current & " " & w)

                If measureSession.Measure(candidate) <= maxWidth Then
                    current = candidate
                Else
                    If current.Length > 0 Then
                        result.Add(current)
                        current = w
                    Else
                        result.Add(FitEllipsis(w, measureSession, maxWidth))
                        current = String.Empty
                    End If
                End If

                If result.Count >= limit Then Exit For
            Next

            If current.Length > 0 AndAlso result.Count < limit Then
                result.Add(current)
            End If

            If result.Count > limit Then
                result.RemoveRange(limit, result.Count - limit)
            End If

            If result.Count = limit AndAlso result.Count > 0 Then
                result(result.Count - 1) =
                    FitEllipsis(result(result.Count - 1), measureSession, maxWidth)
            End If

            Return result
        End Function

        Private Shared Function FitEllipsis(text As String,
                                            measureSession As MASTextWidthMeasureSession,
                                            maxWidth As Single) As String

            Dim s As String = If(text, String.Empty)

            If s.Length = 0 Then Return String.Empty
            If measureSession Is Nothing Then Return s
            If maxWidth <= 0.0F Then Return String.Empty
            If measureSession.Measure(s) <= maxWidth Then Return s

            Const ellipsis As String = "…"

            If measureSession.Measure(ellipsis) > maxWidth Then
                Return String.Empty
            End If

            Dim low As Integer = 0
            Dim high As Integer = s.Length

            While low < high
                Dim mid As Integer = low + ((high - low + 1) \ 2)
                Dim candidate As String = s.Substring(0, mid) & ellipsis

                If measureSession.Measure(candidate) <= maxWidth Then
                    low = mid
                Else
                    high = mid - 1
                End If
            End While

            Return s.Substring(0, low) & ellipsis
        End Function
    End Class

End Namespace
