Imports System.Reflection

Namespace SimpleHistory

    Public Class HistoryStack

        Private stackPast As New Stack(Of HistoryPoint)
        Private stackFuture As New Stack(Of HistoryPoint)

        ''' <summary>
        ''' Gets the count of history points.
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property ChangesCount As Boolean
            Get
                Return stackPast.Count
            End Get
        End Property

        ''' <summary>
        ''' Gets the current stack of all past HistoryPoints that are used for the Undo function.
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property PastHistoryPoints As HistoryPoint()
            Get
                Return stackPast.ToArray
            End Get
        End Property

        ''' <summary>
        ''' Gets the current stack of all future HistoryPoints that are used for the Redo function.
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property FutureHistoryPoints As HistoryPoint()
            Get
                Return stackFuture.ToArray
            End Get
        End Property

        ''' <summary>
        ''' Checks if the History has past changes.
        ''' </summary>
        ''' <returns></returns>
        Public Function HasChanges() As Boolean
            Return stackPast.Count > 0
        End Function

        ''' <summary>
        ''' Patch Object States and call Undo Actions.
        ''' </summary>
        Public Function Undo() As HistoryPoint
            Dim ret As HistoryPoint

            If stackPast.Count > 0 Then
                Dim hp As HistoryPoint = stackPast.Pop
                hp.Undo()
                stackFuture.Push(hp)
                ret = hp
            Else
                ret = Nothing
            End If

            Return ret
        End Function

        ''' <summary>
        ''' Patch Object States and call Redo Actions.
        ''' </summary>
        Public Function Redo() As HistoryPoint
            Dim ret As HistoryPoint

            If stackFuture.Count > 0 Then
                Dim hp As HistoryPoint = stackFuture.Pop
                hp.Redo()
                stackPast.Push(hp)
                ret = hp
            Else
                ret = Nothing
            End If

            Return ret
        End Function

        ''' <summary>
        ''' Clear the History.
        ''' </summary>
        Public Sub Clear()
            stackPast.Clear()
            stackFuture.Clear()
        End Sub

        ''' <summary>
        ''' Store a History Point.
        ''' </summary>
        ''' <param name="point">The History Point to add to the past changes.</param>
        ''' <param name="newName">The name to set for the History Point.</param>
        Public Sub Store(point As HistoryPoint, newName As String)
            point.Name = newName
            Store(point)
        End Sub

        ''' <summary>
        ''' Store a History Point.
        ''' </summary>
        ''' <param name="point">The History Point to add to the past changes.</param>
        Public Sub Store(point As HistoryPoint)
            stackPast.Push(point)
            stackFuture.Clear()
        End Sub

    End Class

End Namespace
