
Namespace Primitives

    ''' <summary>
    ''' Represents a row in an <see cref="Mercury.Mobile.Forms.Primitives.ObjectTable"/>.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class Row

        Private _values As IList(Of Object) = New List(Of Object)()
        Private _cols As IDictionary(Of String, Integer)

        ''' <summary>
        ''' Initializes a new instance of the <see cref="Mercury.Mobile.Forms.Primitives.Row"/> 
        ''' class with the specified table.
        ''' </summary>
        ''' <param name="indexer">An indexer for the column collection.</param>
        ''' <remarks></remarks>
        Protected Friend Sub New(ByVal indexer As IDictionary(Of String, Integer))
            If indexer Is Nothing Then _
                Throw New ArgumentNullException("indexer")
            Me._cols = indexer
        End Sub

#Region "Properties"

        ''' <summary>
        ''' Gets or sets the value of the column at the specified index.
        ''' </summary>
        ''' <param name="index">The index of the column whose value to get or set.</param>
        ''' <returns>The value of the column at the specified index.</returns>
        ''' <remarks></remarks>
        Public Property Item(ByVal index As Integer) As Object
            Get
                If index < 0 OrElse index >= Me._cols.Count Then _
                    Throw New ArgumentOutOfRangeException("index")
                Me._FillToIndex(index, Nothing)
                Return Me._values(index)
            End Get
            Set(ByVal value As Object)
                If index < 0 OrElse index >= Me._cols.Count Then _
                    Throw New ArgumentOutOfRangeException("index")
                Me._FillToIndex(index, Nothing)
                Me._values(index) = value
            End Set
        End Property

        ''' <summary>
        ''' Gets or sets the value of the column associated with the specified column name.
        ''' </summary>
        ''' <param name="columnName">The name of the column whose value to get or set.</param>
        ''' <returns>The value of the column associated with the specified column name.</returns>
        ''' <remarks></remarks>
        Public Property Item(ByVal columnName As String) As Object
            Get
                Dim index = Me._IndexOf(columnName)
                Return Me.Item(index)
            End Get
            Set(ByVal value As Object)
                Dim index = Me._IndexOf(columnName)
                Me.Item(index) = value
            End Set
        End Property

#End Region

#Region "Methods"

        ''' <summary>
        ''' Adds the specified value array corresponding to a value for each column in the row.
        ''' </summary>
        ''' <param name="values">The object array containing the values to add to the row.</param>
        ''' <remarks></remarks>
        Public Sub Add(ByVal ParamArray values() As Object)
            If values IsNot Nothing Then
                Dim actualLen = values.Length + Me._values.Count
                If Me._cols.Count < actualLen Then _
                    Throw New ArgumentException("Too many values supplied for this row.")
                For Each colVal As Object In values
                    Me._values.Add(colVal)
                Next
            End If
        End Sub

        ''' <summary>
        ''' Adds the specified data value to the next available column in this row.
        ''' </summary>
        ''' <param name="value">The value to add to the row.</param>
        ''' <remarks></remarks>
        Public Sub Add(ByVal value As Object)
            If Me._values.Count >= Me._cols.Count Then _
                Throw New ArgumentException("Too many values supplied for this row.")
            Me._values.Add(value)
        End Sub

        ''' <summary>
        ''' Inserts the specified value at the specified index.
        ''' </summary>
        ''' <param name="index">The index at which to insert the value.</param>
        ''' <param name="value">The value to insert.</param>
        ''' <remarks></remarks>
        Public Sub Insert(ByVal index As Integer, ByVal value As Object)
            If index < 0 OrElse index >= Me._cols.Count Then _
                Throw New ArgumentOutOfRangeException("index")
            Me._FillToIndex(index, Nothing)
            Me._values(index) = value
        End Sub

        ''' <summary>
        ''' Determines whether the item at the specified column index contains a null value.
        ''' </summary>
        ''' <param name="index">The zero-based index of the column to check.</param>
        ''' <returns>True if the column contains a null value; otherwise, false.</returns>
        ''' <remarks></remarks>
        Public Function IsNull(ByVal index As Integer) As Boolean
            If index < 0 OrElse index >= Me._cols.Count Then _
                Throw New ArgumentOutOfRangeException("index")
            Return (Me.Item(index) Is Nothing)
        End Function

        ''' <summary>
        ''' Determines whether the item associated with the specified column name contains a null value.
        ''' </summary>
        ''' <param name="columnName">The name of the column to check.</param>
        ''' <returns>True if the column contains a null value; otherwise, false.</returns>
        ''' <remarks></remarks>
        Public Function IsNull(ByVal columnName As String) As Boolean
            Dim index = Me._IndexOf(columnName)
            Return Me.IsNull(index)
        End Function

        ''' <summary>
        ''' Sets the value of the item at the specified column index to null.
        ''' </summary>
        ''' <param name="index">The zero-based index of the column to set.</param>
        ''' <remarks></remarks>
        Public Sub SetNull(ByVal index As Integer)
            Me.Item(index) = Nothing
        End Sub

        ''' <summary>
        ''' Sets the value of the item associated with the specified column name to null.
        ''' </summary>
        ''' <param name="columnName">The name of the column to set.</param>
        ''' <remarks></remarks>
        Public Sub SetNull(ByVal columnName As String)
            Me.Item(columnName) = Nothing
        End Sub

        Private Sub _FillToIndex(ByVal index As Integer, ByVal value As Object)
            If index < Me._values.Count Then _
                Return
            For i As Integer = Me._values.Count To index
                Me._values.Add(value)
            Next
        End Sub

        Private Function _IndexOf(ByVal columnName As String) As Integer
            If columnName IsNot Nothing AndAlso Me._cols.ContainsKey(columnName) Then _
                Return Me._cols(columnName)
            Return -1
        End Function

#End Region

    End Class

End Namespace