Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Windows.Forms
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Composition
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    Partial Public NotInheritable Class MASPivotTable

#Region "Helpers"

        Private Function FindRow(rowKey As String) As PivotRowState
            Dim normalized As String = If(rowKey, String.Empty).Trim()
            If normalized.Length = 0 Then Return Nothing
            Dim row As PivotRowState = Nothing
            If _rowLookup.TryGetValue(normalized, row) Then Return row
            Return Nothing
        End Function

        Private Function FindColumn(columnKey As String) As PivotColumnState
            Dim normalized As String = If(columnKey, String.Empty).Trim()
            If normalized.Length = 0 Then Return Nothing
            Dim column As PivotColumnState = Nothing
            If _columnLookup.TryGetValue(normalized, column) Then Return column
            Return Nothing
        End Function

        Private Sub EnsureSummaryCache()
            If _summaryCacheRevision = _summaryRevision Then Return
            _rowTotals.Clear()
            _columnTotals.Clear()
            _grandTotal = 0D

            For Each row As PivotRowState In _rows
                _rowTotals(row.Key) = 0D
            Next
            For Each column As PivotColumnState In _columns
                _columnTotals(column.Key) = 0D
            Next

            For Each pair As KeyValuePair(Of String, Decimal) In _values
                If pair.Value = 0D Then Continue For
                Dim rowKey As String = String.Empty
                Dim columnKey As String = String.Empty
                If Not TrySplitCellKey(pair.Key, rowKey, columnKey) Then Continue For
                If Not _rowLookup.ContainsKey(rowKey) OrElse Not _columnLookup.ContainsKey(columnKey) Then Continue For
                _rowTotals(rowKey) = _rowTotals(rowKey) + pair.Value
                _columnTotals(columnKey) = _columnTotals(columnKey) + pair.Value
                _grandTotal += pair.Value
            Next

            _summaryCacheRevision = _summaryRevision
        End Sub

        Private Sub InvalidateSummaryCache(reason As String)
            If _summaryRevision = Integer.MaxValue Then
                _summaryRevision = 0
                _summaryCacheRevision = -1
            Else
                _summaryRevision += 1
            End If
        End Sub

        Private Shared Function BuildCellKey(rowKey As String, columnKey As String) As String
            Return If(rowKey, String.Empty) & ChrW(30) & If(columnKey, String.Empty)
        End Function

        Private Shared Function TrySplitCellKey(cellKey As String,
                                                ByRef rowKey As String,
                                                ByRef columnKey As String) As Boolean
            rowKey = String.Empty
            columnKey = String.Empty
            Dim key As String = If(cellKey, String.Empty)
            Dim separatorIndex As Integer = key.IndexOf(ChrW(30))
            If separatorIndex < 0 Then Return False
            rowKey = key.Substring(0, separatorIndex)
            columnKey = key.Substring(separatorIndex + 1)
            Return rowKey.Length > 0 AndAlso columnKey.Length > 0
        End Function

        Private Shared Function Inset(rect As SKRect, amount As Single) As SKRect
            Return New SKRect(rect.Left + amount, rect.Top + amount, rect.Right - amount, rect.Bottom - amount)
        End Function

        Private Shared Function InsetHorizontal(rect As SKRect, amount As Single) As SKRect
            Return New SKRect(rect.Left + amount, rect.Top, rect.Right - amount, rect.Bottom)
        End Function

        Private Shared Sub DrawVerticalDivider(canvas As SKCanvas,
                                               rect As SKRect,
                                               dpi As Single,
                                               accent As SKColor)
            Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, dpi), .Color = accent.WithAlpha(PivotTableTokens.DividerAlpha)}
                canvas.DrawLine(rect.Left, rect.Top + 6.0F * dpi, rect.Left, rect.Bottom - 6.0F * dpi, stroke)
            End Using
        End Sub

        Private Sub RaisePivotTableChangedSafe()
            Try
                RaiseEvent PivotTableChanged(Me, EventArgs.Empty)
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowInputBoundary(ex, "MASPivotTable.PivotTableChanged")
            End Try
        End Sub

        Private Sub RaiseSelectedCellChangedSafe()
            Try
                RaiseEvent SelectedCellChanged(Me, EventArgs.Empty)
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowInputBoundary(ex, "MASPivotTable.SelectedCellChanged")
            End Try
        End Sub

        Friend Function CreatePivotTableReadinessManifest() As MASPivotTableReadinessManifest
            Return MASPivotTableReadinessManifest.CreateDefault()
        End Function

#End Region

    End Class

End Namespace
