Imports System.Runtime.CompilerServices

''' <summary>
''' A set of array extensions.
''' </summary>
''' <remarks></remarks>
Public Module ArrayExtensions

    ''' <summary>
    ''' Traverses all items and dimensions in an array and performs the specified action on each one.
    ''' </summary>
    ''' <param name="arr">The array to traverse.</param>
    ''' <param name="action">The action to perform.</param>
    ''' <remarks></remarks>
    <Extension()> _
    Public Sub Traverse(ByVal arr As Array, ByVal cloneArray As Array, ByVal visited As IDictionary(Of Object, Object), ByVal action As Action(Of Array, Integer(), Array, IDictionary(Of Object, Object)))
#If FULL_FRAME Then
        If (arr.LongLength = 0) Then _
            Return
#Else
        If (arr.Length = 0) Then _
            Return
#End If
        If (action Is Nothing) Then _
            Return
        Dim walker = New ArrayWalker(arr)
        Do
            action.Invoke(arr, walker.Position, cloneArray, visited)
        Loop While (walker.Step())
    End Sub

    Friend Class ArrayWalker

        Public Position() As Integer
        Public MaxLengths() As Integer

        Public Sub New(ByVal arr As Array)
            Me.MaxLengths = New Integer(arr.Rank - 1) {}
            For i As Integer = 0 To arr.Rank - 1
                Me.MaxLengths(i) = arr.GetLength(i) - 1
            Next
            Me.Position = New Integer(arr.Rank - 1) {}
        End Sub

        Public Function [Step]() As Boolean
            For i As Integer = 0 To Me.Position.Length - 1
                If Me.Position(i) < Me.MaxLengths(i) Then
                    Me.Position(i) += 1
                    For j As Integer = 0 To i - 1
                        Me.Position(j) = 0
                    Next
                    Return True
                End If
            Next
            Return False
        End Function

    End Class
End Module