Imports Mercury.Mobile.Collections
Imports System.Text

''' <summary>
''' Represents a 3-tuple, or triple.
''' </summary>
''' <typeparam name="T1">The type of the tuple's first component.</typeparam>
''' <typeparam name="T2">The type of the tuple's second component.</typeparam>
''' <typeparam name="T3">The type of the tuple's third component.</typeparam>
''' <remarks></remarks>
Public Class Tuple(Of T1, T2, T3)
    Implements IStructuralEquatable, IStructuralComparable, IComparable, ITuple

    ''' <summary>
    ''' Initializes a new instance of the specified <see cref="T:Mercury.Mobile.Tuple'3"/> class.
    ''' </summary>
    ''' <param name="item1">The value of the tuple's first component.</param>
    ''' <param name="item2">The value of the tuple's second component.</param>
    ''' <param name="item3">The value of the tuple's third component.</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal item1 As T1, ByVal item2 As T2, ByVal item3 As T3)
        Me.m_item1 = item1
        Me.m_item2 = item2
        Me.m_item3 = item3
    End Sub

    Private ReadOnly m_item1 As T1
    Private ReadOnly m_item2 As T2
    Private ReadOnly m_item3 As T3

    ''' <summary>
    ''' Gets the value of the <see cref="T:Mercury.Mobile.Tuple'3"/> object's first component.
    ''' </summary>
    ''' <returns>The value of the <see cref="T:Mercury.Mobile.Tuple'3"/> object's first component.</returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Item1() As T1
        Get
            Return Me.m_item1
        End Get
    End Property

    ''' <summary>
    ''' Gets the value of the <see cref="T:Mercury.Mobile.Tuple'3"/> object's second component.
    ''' </summary>
    ''' <returns>The value of the <see cref="T:Mercury.Mobile.Tuple'3"/> object's second component.</returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Item2() As T2
        Get
            Return Me.m_item2
        End Get
    End Property

    ''' <summary>
    ''' Gets the value of the <see cref="T:Mercury.Mobile.Tuple'3"/> object's second component.
    ''' </summary>
    ''' <returns>The value of the <see cref="T:Mercury.Mobile.Tuple'3"/> object's second component.</returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Item3() As T3
        Get
            Return Me.m_item3
        End Get
    End Property


    Private ReadOnly Property Size() As Integer Implements ITuple.Size
        Get
            Return 3
        End Get
    End Property

    ''' <summary>
    ''' Returns a value that indicates whether the current <see cref="T:Mercury.Mobile.Tuple'3"/> object is equal to a specified object.
    ''' </summary>
    ''' <param name="obj">The object to compare with this instance.</param>
    ''' <returns>True if the current instance is equal to the specified object; otherwise, false.</returns>
    ''' <remarks></remarks>
    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        Return CType(Me, IStructuralEquatable).Equals(obj, EqualityComparer(Of Object).Default)
    End Function

    Private Function Equals1(ByVal other As Object, ByVal comparer As System.Collections.IEqualityComparer) As Boolean Implements Collections.IStructuralEquatable.Equals
        If other Is Nothing Then _
            Return False
        Dim tuple = TryCast(other, Tuple(Of T1, T2, T3))
        Return tuple IsNot Nothing AndAlso comparer.Equals(Me.m_item1, tuple.m_item1) AndAlso comparer.Equals(Me.m_item2, tuple.m_item2)
    End Function

    Private Function CompareTo1(ByVal obj As Object) As Integer Implements System.IComparable.CompareTo
        Return CType(Me, IStructuralComparable).CompareTo(obj, EqualityComparer(Of Object).Default)
    End Function

    Private Function CompareTo(ByVal other As Object, ByVal comparer As System.Collections.IComparer) As Integer Implements Collections.IStructuralComparable.CompareTo
        If other Is Nothing Then _
            Return 1
        Dim tuple = TryCast(other, Tuple(Of T1, T2, T3))
        If tuple Is Nothing Then
            Throw New ArgumentException(String.Format(My.Resources.Culture, _
                My.Resources.ArgumentException_IncorrectType, "other", MyBase.GetType().ToString()))
        End If
        Dim num = comparer.Compare(Me.m_item1, tuple.m_item1)
        If num <> 0 Then _
            Return num
        num = comparer.Compare(Me.m_item2, tuple.m_item2)
        If num <> 0 Then _
            Return num
        Return comparer.Compare(Me.m_item3, tuple.m_item3)
    End Function

    ''' <summary>
    ''' Returns the hash code for the current <see cref="T:Mercury.Mobile.Tuple'3"/> object.
    ''' </summary>
    ''' <returns>A 32-bit signed integer hash code.</returns>
    ''' <remarks></remarks>
    Public Overrides Function GetHashCode() As Integer
        Return CType(Me, IStructuralEquatable).GetHashCode(EqualityComparer(Of Object).Default)
    End Function

    Private Function GetHashCode1(ByVal comparer As System.Collections.IEqualityComparer) As Object Implements Collections.IStructuralEquatable.GetHashCode
        Return Tuple.CombineHashCodes(comparer.GetHashCode(Me.m_item1), comparer.GetHashCode(Me.m_item2), comparer.GetHashCode(Me.m_item3))
    End Function

    Private Function GetHashCode2(ByVal comparer As System.Collections.IEqualityComparer) As Integer Implements ITuple.GetHashCode
        Return CType(Me, IStructuralEquatable).GetHashCode(comparer)
    End Function

    ''' <summary>
    ''' Returns a string that represents the value of this <see cref="T:Mercury.Mobile.Tuple'3"/> instance.
    ''' </summary>
    ''' <returns>The string representation of this <see cref="T:Mercury.Mobile.Tuple'3"/> object.</returns>
    ''' <remarks></remarks>
    Public Overrides Function ToString() As String
        Dim sb = New StringBuilder()
        sb.Append("(")
        Return CType(Me, ITuple).ToString(sb)
    End Function

    Private Function ToString1(ByVal sb As System.Text.StringBuilder) As String Implements ITuple.ToString
        sb.Append(Me.m_item1)
        sb.Append(", ")
        sb.Append(Me.m_item2)
        sb.Append(", ")
        sb.Append(Me.m_item3)
        sb.Append(")")
        Return sb.ToString()
    End Function

End Class