Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations

Namespace TraditionalIndexing
    Public Class Customer
        Implements INotifyPropertyChanged, IEditableObject
        Private _id As Integer
        Private _first, _last, _country As String
        Private _active As Boolean
        Private _hired As Date
        Private _weight As Double

        Private Shared _rnd As New Random()
        Private Shared _firstNames() As String = "Andy|Ben|Charlie|Dan|Ed|Fred|Gil|Herb|Jack|Karl|Larry|Mark|Noah|Oprah|Paul|Quince|Rich|Steve|Ted|Ulrich|Vic|Xavier|Zeb".Split("|"c)
        Private Shared _lastNames() As String = "Ambers|Bishop|Cole|Danson|Evers|Frommer|Griswold|Heath|Jammers|Krause|Lehman|Myers|Neiman|Orsted|Paulson|Quaid|Richards|Stevens|Trask|Ulam".Split("|"c)
        Private Shared _countries() As String = "China|India|United States|Indonesia|Brazil|Pakistan|Bangladesh|Nigeria|Russia|Japan|Mexico|Philippines|Vietnam|Germany|Ethiopia|Egypt|Iran|Turkey|Congo|France|Thailand|United Kingdom|Italy|Myanmar".Split("|"c)

        Public Sub New()
            Me.New(_rnd.Next())

        End Sub
        Public Sub New(ByVal id As Integer)
            Me.ID = id

            First = GetString(_firstNames)
            Last = GetString(_lastNames)
            Country = GetString(_countries)
            Active = _rnd.NextDouble() >= 0.5
            Hired = Date.Today.AddDays(-_rnd.Next(1, 365))
            Weight = 50 + _rnd.NextDouble() * 50
            Father = GetName()
            Brother = GetName()
            Cousin = GetName()
            Boss = GetName()
            [Friend] = GetName()
            Driver = GetName()
            Enemy = GetName()
        End Sub

        <Display(Name:="ID")>
        Public Property ID() As Integer
            Get
                Return _id
            End Get
            Set(ByVal value As Integer)
                If value <> _id Then
                    _id = value
                    OnPropertyChanged("ID")
                End If
            End Set
        End Property

        <Display(Name:="Name")>
        Public ReadOnly Property Name() As String
            Get
                Return String.Format("{0} {1}", First, Last)
            End Get
        End Property

        <Display(Name:="Country")>
        Public Property Country() As String
            Get
                Return _country
            End Get
            Set(ByVal value As String)
                If value <> _country Then
                    _country = value
                    OnPropertyChanged("Country")
                End If
            End Set
        End Property

        <Display(Name:="Active")>
        Public Property Active() As Boolean
            Get
                Return _active
            End Get
            Set(ByVal value As Boolean)
                If value <> _active Then
                    _active = value
                    OnPropertyChanged("Active")
                End If
            End Set
        End Property

        <Display(Name:="First")>
        Public Property First() As String
            Get
                Return _first
            End Get
            Set(ByVal value As String)
                If value <> _first Then
                    _first = value
                    OnPropertyChanged("First")
                End If
            End Set
        End Property

        <Display(Name:="Last")>
        Public Property Last() As String
            Get
                Return _last
            End Get
            Set(ByVal value As String)
                If value <> _last Then
                    _last = value
                    OnPropertyChanged("Last")
                End If
            End Set
        End Property

        <Display(Name:="Hired")>
        Public Property Hired() As Date
            Get
                Return _hired
            End Get
            Set(ByVal value As Date)
                If value <> _hired Then
                    _hired = value
                    OnPropertyChanged("Hired")
                End If
            End Set
        End Property

        <Display(Name:="Weight")>
        Public Property Weight() As Double
            Get
                Return _weight
            End Get
            Set(ByVal value As Double)
                If value <> _weight Then
                    _weight = value
                    OnPropertyChanged("Weight")
                End If
            End Set
        End Property

        ' some read-only stuff
        Private privateFather As String
        <Display(Name:="Father")>
        Public Property Father() As String
            Get
                Return privateFather
            End Get
            Private Set(ByVal value As String)
                privateFather = value
            End Set
        End Property
        Private privateBrother As String
        <Display(Name:="Brother")>
        Public Property Brother() As String
            Get
                Return privateBrother
            End Get
            Private Set(ByVal value As String)
                privateBrother = value
            End Set
        End Property
        Private privateCousin As String
        <Display(Name:="Cousin")>
        Public Property Cousin() As String
            Get
                Return privateCousin
            End Get
            Private Set(ByVal value As String)
                privateCousin = value
            End Set
        End Property
        Private privateBoss As String
        <Display(Name:="Boss")>
        Public Property Boss() As String
            Get
                Return privateBoss
            End Get
            Private Set(ByVal value As String)
                privateBoss = value
            End Set
        End Property
        Private privateFriend As String
        <Display(Name:="Friend")>
        Public Property [Friend]() As String
            Get
                Return privateFriend
            End Get
            Private Set(ByVal value As String)
                privateFriend = value
            End Set
        End Property
        Private privateDriver As String
        <Display(Name:="Driver")>
        Public Property Driver() As String
            Get
                Return privateDriver
            End Get
            Private Set(ByVal value As String)
                privateDriver = value
            End Set
        End Property
        Private privateEnemy As String
        <Display(Name:="Enemy")>
        Public Property Enemy() As String
            Get
                Return privateEnemy
            End Get
            Private Set(ByVal value As String)
                privateEnemy = value
            End Set
        End Property

        Private Shared Function GetString(ByVal arr() As String) As String
            Return arr(_rnd.Next(arr.Length))
        End Function
        Private Shared Function GetName() As String
            Return String.Format("{0} {1}", GetString(_firstNames), GetString(_lastNames))
        End Function

        '-----------------------------------------------------------------------------------
#Region "INotifyPropertyChanged Members"

        Private Sub OnPropertyChanged(ByVal propertyName As String)
            OnPropertyChanged(New PropertyChangedEventArgs(propertyName))
        End Sub
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
        Protected Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)
            RaiseEvent PropertyChanged(Me, e)
        End Sub

#End Region

        '-----------------------------------------------------------------------------------
#Region "IEditableObject Members"

        Private _clone As Customer
        Public Sub BeginEdit() Implements IEditableObject.BeginEdit
            _clone = CType(Me.MemberwiseClone(), Customer)
        End Sub
        Public Sub EndEdit() Implements IEditableObject.EndEdit
            _clone = Nothing
        End Sub
        Public Sub CancelEdit() Implements IEditableObject.CancelEdit
            If _clone IsNot Nothing Then
                _id = _clone._id
                _first = _clone._first
                _last = _clone._last
                _country = _clone._country
                _active = _clone._active
                _hired = _clone._hired
                _weight = _clone._weight
            End If
        End Sub

#End Region

    End Class
End Namespace
