Imports System.Reflection

Namespace SimpleHistory

    ''' <summary>
    ''' Represent some Object States and Actions.
    ''' </summary>
    Public Class HistoryPoint

        ''' <summary>
        ''' Represents the Name of this History Point
        ''' </summary>
        ''' <returns></returns>
        Public Property Name As String = ""
        ''' <summary>
        ''' A List of Object States and Actions.
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property Entries As New List(Of ObjectBase)
        ''' <summary>
        ''' Some data can be refered on this HistoryPoint. Don't know, in some situations this can be helpful.
        ''' </summary>
        Public ReadOnly Tag As Object = Nothing

        Public Function HasEntries(Of T As ObjectBase)() As Boolean
            Return Entries.Where(Function(n) TypeOf n Is T).Count > 0
        End Function

        Friend Sub Undo()
            For Each s As ObjectBase In Entries.OrderBy(Function(n) n.UndoPriority)
                If TypeOf s Is ObjectState Then
                    CType(s, ObjectState).Patch()
                ElseIf TypeOf s Is ObjectAction Then
                    CType(s, ObjectAction).Undo()
                End If
            Next
        End Sub

        Friend Sub Redo()
            For Each s As ObjectBase In Entries.OrderBy(Function(n) n.RedoPriority)
                If TypeOf s Is ObjectState Then
                    CType(s, ObjectState).Patch()
                ElseIf TypeOf s Is ObjectAction Then
                    CType(s, ObjectAction).Redo()
                End If
            Next
        End Sub

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="whiteList">Specify which members to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), whiteList As MemberWhiteList) As HistoryPoint
            Return FromObject({obj}, ObjectValueType.None, CObj(whiteList), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="blackList">Specify which members to exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), blackList As MemberBlackList) As HistoryPoint
            Return FromObject({obj}, ObjectValueType.None, CObj(blackList), BindingFlags.Default)
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="memberName">The member names to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
            Else
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
            End If
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="memberName">The member names to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, membersToStore, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
            Else
                Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
            End If
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="memberName">The member names to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, flags, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), flags)
            Else
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), flags)
            End If
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="memberName">The member names to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, flags, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object(), membersToStore As ObjectValueType, flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), flags)
            Else
                Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), flags)
            End If
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="whiteList">Specify which members to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, whiteList As MemberWhiteList) As HistoryPoint
            Return FromObject({obj}, ObjectValueType.None, CObj(whiteList), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="blackList">Specify which members to exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, blackList As MemberBlackList) As HistoryPoint
            Return FromObject({obj}, ObjectValueType.None, CObj(blackList), BindingFlags.Default)
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
            Else
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
            End If
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="memberName">The member names to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, membersToStore, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), BindingFlags.Default)
            Else
                Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), BindingFlags.Default)
            End If
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="memberName">The member names to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, flags, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberWhiteList(memberName)), flags)
            Else
                Return FromObject({obj}, ObjectValueType.None, CObj(New MemberBlackList(memberName)), flags)
            End If
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="memberName">The member names to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, flags As BindingFlags, ParamArray memberName As String()) As HistoryPoint
            Return FromObject(obj, flags, True, memberName)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <param name="isWhiteList">If true, the memberName-Array has member names that should be included.</param>
        ''' <param name="memberName">The member names to include/exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, flags As BindingFlags, isWhiteList As Boolean, ParamArray memberName As String()) As HistoryPoint
            If isWhiteList Then
                Return FromObject({obj}, membersToStore, CObj(New MemberWhiteList(memberName)), flags)
            Else
                Return FromObject({obj}, membersToStore, CObj(New MemberBlackList(memberName)), flags)
            End If
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object) As HistoryPoint
            Return FromObject({obj}, ObjectValueType.None, CObj(Nothing), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType) As HistoryPoint
            Return FromObject({obj}, membersToStore, CObj(Nothing), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="whiteList">Specify which members to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, whiteList As MemberWhiteList) As HistoryPoint
            Return FromObject({obj}, membersToStore, CObj(whiteList), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="blackList">Specify which members to exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, blackList As MemberBlackList) As HistoryPoint
            Return FromObject({obj}, membersToStore, CObj(blackList), BindingFlags.Default)
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, flags As BindingFlags) As HistoryPoint
            Return FromObject({obj}, ObjectValueType.None, CObj(Nothing), flags)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, flags As BindingFlags) As HistoryPoint
            Return FromObject({obj}, membersToStore, CObj(Nothing), flags)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="whiteList">Specify which members to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, whiteList As MemberWhiteList, flags As BindingFlags) As HistoryPoint
            Return FromObject({obj}, membersToStore, CObj(whiteList), flags)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="obj">The object that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="blackList">Specify which members to exclude.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(obj As Object, membersToStore As ObjectValueType, blackList As MemberBlackList, flags As BindingFlags) As HistoryPoint
            Return FromObject({obj}, membersToStore, CObj(blackList), flags)
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object()) As HistoryPoint
            Return FromObject(objs, ObjectValueType.None, CObj(Nothing), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType) As HistoryPoint
            Return FromObject(objs, membersToStore, CObj(Nothing), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="whiteList">Specify which members to include.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, whiteList As MemberWhiteList) As HistoryPoint
            Return FromObject(objs, membersToStore, CObj(whiteList), BindingFlags.Default)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="blackList">Specify which members to exclude.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, blackList As MemberBlackList) As HistoryPoint
            Return FromObject(objs, membersToStore, CObj(blackList), BindingFlags.Default)
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object(), flags As BindingFlags) As HistoryPoint
            Return FromObject(objs, ObjectValueType.None, CObj(Nothing), flags)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, flags As BindingFlags) As HistoryPoint
            Return FromObject(objs, membersToStore, CObj(Nothing), flags)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="whiteList">Specify which members to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, whiteList As MemberWhiteList, flags As BindingFlags) As HistoryPoint
            Return FromObject(objs, membersToStore, CObj(whiteList), flags)
        End Function
        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="blackList">Specify which members to exclude.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Public Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, blackList As MemberBlackList, flags As BindingFlags) As HistoryPoint
            Return FromObject(objs, membersToStore, CObj(blackList), flags)
        End Function

        ''' <summary>
        ''' Creates an History Point with Object States automaticly from input.
        ''' </summary>
        ''' <param name="objs">The objects that should be included.</param>
        ''' <param name="membersToStore">Specify what member types to include.</param>
        ''' <param name="whiteOrBlackList">Specify which members to include.</param>
        ''' <param name="flags">The Binding Flags that the members should have.</param>
        ''' <returns>A History Point with Object States.</returns>
        Private Shared Function FromObject(objs As Object(), membersToStore As ObjectValueType, whiteOrBlackList As Object, flags As BindingFlags) As HistoryPoint
            Dim hp As New HistoryPoint

            If whiteOrBlackList Is Nothing Then whiteOrBlackList = New MemberBlackList
            Dim isWhiteList As Boolean = TypeOf whiteOrBlackList Is MemberWhiteList

            If flags = BindingFlags.Default Then
                flags = BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic
            End If
            If membersToStore = ObjectValueType.None Then
                membersToStore = ObjectValueType.Field Or ObjectValueType.Property
            End If

            For Each obj As Object In objs
                If (membersToStore And ObjectValueType.Field) = ObjectValueType.Field Then

                    For Each fi As FieldInfo In obj.GetType.GetFields(flags)

                        Dim contains As Boolean = CType(whiteOrBlackList, List(Of String)).Contains(fi.Name)
                        If If(isWhiteList, contains, Not contains) Then

                            Dim os As New ObjectState
                            os.Object = obj
                            os.MemberName = fi.Name
                            os.MemberType = ObjectValueType.Field
                            os.MemberFlags = flags
                            os.ValueToPatch = fi.GetValue(obj)
                            hp.Entries.Add(os)

                        End If

                    Next

                End If

                If (membersToStore And ObjectValueType.Property) = ObjectValueType.Property Then

                    For Each pi As PropertyInfo In obj.GetType.GetProperties(flags)

                        Dim contains As Boolean = CType(whiteOrBlackList, List(Of String)).Contains(pi.Name)
                        If If(isWhiteList, contains, Not contains) Then

                            Dim os As New ObjectState
                            os.Object = obj
                            os.MemberName = pi.Name
                            os.MemberType = ObjectValueType.Property
                            os.MemberFlags = flags
                            os.ValueToPatch = pi.GetValue(obj)
                            hp.Entries.Add(os)

                        End If

                    Next

                End If
            Next

            Return hp
        End Function

        ''' <summary>
        ''' Combines some History Points to one.
        ''' </summary>
        ''' <param name="hps">An array of History Points to combine.</param>
        ''' <returns>One History Point that contains all Data of inputted History Points.</returns>
        Public Shared Function Concat(ParamArray hps As HistoryPoint()) As HistoryPoint
            Return Concat(hps.FirstOrDefault?.Name, hps)
        End Function

        ''' <summary>
        ''' Combines some History Points to one.
        ''' </summary>
        ''' <param name="hps">An array of History Points to combine.</param>
        ''' <returns>One History Point that contains all Data of inputted History Points.</returns>
        Public Shared Function Concat(newName As String, ParamArray hps As HistoryPoint()) As HistoryPoint
            Dim hp As New HistoryPoint

            For Each _hp As HistoryPoint In hps
                hp.Entries.AddRange(_hp.Entries)
            Next

            Return hp
        End Function

    End Class

End Namespace
