Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic

Namespace Nexamas.UI.General

    Friend NotInheritable Class MASNavigationHistory(Of T)

        Private ReadOnly _backStack As New Stack(Of T)()
        Private ReadOnly _forwardStack As New Stack(Of T)()
        Private ReadOnly _isEmpty As Func(Of T, Boolean)

        Friend Sub New(Optional isEmpty As Func(Of T, Boolean) = Nothing)
            _isEmpty = If(isEmpty, Function(value As T) value Is Nothing)
        End Sub

        Friend Sub Clear()
            _backStack.Clear()
            _forwardStack.Clear()
        End Sub

        Friend ReadOnly Property CanGoBack As Boolean
            Get
                Return _backStack.Count > 0
            End Get
        End Property

        Friend ReadOnly Property CanGoForward As Boolean
            Get
                Return _forwardStack.Count > 0
            End Get
        End Property

        Friend Sub RecordNavigation(previousItem As T)
            If IsEmptyValue(previousItem) Then Return

            _backStack.Push(previousItem)
            _forwardStack.Clear()
        End Sub

        Friend Function TryMoveBack(currentItem As T, ByRef target As T) As Boolean
            target = Nothing

            If _backStack.Count <= 0 Then Return False

            If Not IsEmptyValue(currentItem) Then
                _forwardStack.Push(currentItem)
            End If

            target = _backStack.Pop()
            Return Not IsEmptyValue(target)
        End Function

        Friend Function TryMoveForward(currentItem As T, ByRef target As T) As Boolean
            target = Nothing

            If _forwardStack.Count <= 0 Then Return False

            If Not IsEmptyValue(currentItem) Then
                _backStack.Push(currentItem)
            End If

            target = _forwardStack.Pop()
            Return Not IsEmptyValue(target)
        End Function

        Private Function IsEmptyValue(value As T) As Boolean
            Try
                Return _isEmpty.Invoke(value)
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowFileSystemBoundary(masCaughtException1)
                Return True
            End Try
        End Function

    End Class

End Namespace