Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Text

Namespace Nexamas.UI.DataBinding

    ''' <summary>
    ''' Friend-only immutable multi-level pivot grouping path. It normalizes group
    ''' segments into deterministic display labels and stable keys without adding
    ''' query, OLAP, Excel, storage, or provider ownership to PivotTable.
    ''' </summary>
    Friend NotInheritable Class MASPivotGroupPath
        Private ReadOnly _segments As IReadOnlyList(Of String)

        Friend Sub New(segments As IEnumerable(Of Object))
            Dim normalized As New List(Of String)()
            If segments IsNot Nothing Then
                For Each segment As Object In segments
                    Dim text As String = NormalizeSegment(segment)
                    If text.Length > 0 Then normalized.Add(text)
                Next
            End If
            If normalized.Count = 0 Then normalized.Add("(blank)")
            _segments = New ReadOnlyCollection(Of String)(normalized)
            Me.DisplayLabel = BuildDisplayLabel(_segments)
            Me.StableKey = BuildStableKey(_segments)
        End Sub

        Friend ReadOnly Property Segments As IReadOnlyList(Of String)
            Get
                Return _segments
            End Get
        End Property

        Friend ReadOnly Property DisplayLabel As String
        Friend ReadOnly Property StableKey As String

        Friend ReadOnly Property Depth As Integer
            Get
                Return _segments.Count
            End Get
        End Property

        Friend Shared Function Create(ParamArray segments As Object()) As MASPivotGroupPath
            Return New MASPivotGroupPath(segments)
        End Function

        Private Shared Function NormalizeSegment(value As Object) As String
            Dim text As String = Convert.ToString(value, CultureInfo.CurrentCulture)
            text = If(text, String.Empty).Trim()
            text = text.Replace(ControlChars.Cr, " "c).Replace(ControlChars.Lf, " "c).Replace(ControlChars.Tab, " "c)
            While text.Contains("  ")
                text = text.Replace("  ", " ")
            End While
            If text.Length = 0 Then text = "(blank)"
            If text.Length > 72 Then text = text.Substring(0, 72)
            Return text
        End Function

        Private Shared Function BuildDisplayLabel(segments As IReadOnlyList(Of String)) As String
            Return String.Join(" / ", segments)
        End Function

        Private Shared Function BuildStableKey(segments As IReadOnlyList(Of String)) As String
            Dim builder As New StringBuilder()
            For i As Integer = 0 To segments.Count - 1
                If i > 0 Then builder.Append("|")
                builder.Append(EscapeStableSegment(segments(i)))
            Next
            Return builder.ToString()
        End Function

        Private Shared Function EscapeStableSegment(segment As String) As String
            Dim text As String = If(segment, String.Empty)
            text = text.Replace("\", "\\")
            text = text.Replace("|", "\p")
            Return text
        End Function
    End Class

End Namespace
