//-----------------------------------------------------------------------
// 
//     Copyright (c) Microsoft Corporation.
// 
//-----------------------------------------------------------------------
namespace Microsoft.Isam.Esent.Interop
{
    using System;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Runtime.InteropServices;
    /// 
    /// Describes an offset in the log sequence.
    /// 
    [SuppressMessage(
        "Microsoft.StyleCop.CSharp.NamingRules",
        "SA1300:ElementMustBeginWithUpperCaseLetter",
        Justification = "This should match the name of the unmanaged structure.")]
    [StructLayout(LayoutKind.Sequential)]
    [Serializable]
    public struct JET_LGPOS : IEquatable, IComparable, INullableJetStruct
    {
        /// 
        /// Byte offset inside the sector.
        /// 
        private ushort offset;
        /// 
        /// Sector number.
        /// 
        private ushort sector;
        /// 
        /// Generation number.
        /// 
        private int generation;
        /// 
        /// Gets or sets the byte offset represented by this log position. This
        /// offset is inside of the sector.
        /// 
        public int ib
        {
            [DebuggerStepThrough]
            get { return this.offset; }
            set { this.offset = checked((ushort)value); }
        }
        /// 
        /// Gets or sets the sector number represented by this log position.
        /// 
        public int isec
        {
            [DebuggerStepThrough]
            get { return this.sector; }
            set { this.sector = checked((ushort)value); }
        }
        /// 
        /// Gets or sets the generation of this log position.
        /// 
        public int lGeneration
        {
            [DebuggerStepThrough]
            get { return this.generation; }
            set { this.generation = value; }
        }
        /// 
        /// Gets a value indicating whether this log position is null.
        /// 
        public bool HasValue
        {
            get
            {
                return 0 != this.lGeneration;
            }
        }
        /// 
        /// Determines whether two specified instances of JET_LGPOS
        /// are equal.
        /// 
        /// The first instance to compare.
        /// The second instance to compare.
        /// True if the two instances are equal.
        public static bool operator ==(JET_LGPOS lhs, JET_LGPOS rhs)
        {
            return lhs.Equals(rhs);
        }
        /// 
        /// Determines whether two specified instances of JET_LGPOS
        /// are not equal.
        /// 
        /// The first instance to compare.
        /// The second instance to compare.
        /// True if the two instances are not equal.
        public static bool operator !=(JET_LGPOS lhs, JET_LGPOS rhs)
        {
            return !(lhs == rhs);
        }
        /// 
        /// Determine whether one log position is before another log position.
        /// 
        /// The first log position to compare.
        /// The second log position to compare.
        /// True if lhs comes before rhs.
        public static bool operator <(JET_LGPOS lhs, JET_LGPOS rhs)
        {
            return lhs.CompareTo(rhs) < 0;
        }
        /// 
        /// Determine whether one log position is after another log position.
        /// 
        /// The first log position to compare.
        /// The second log position to compare.
        /// True if lhs comes after rhs.
        public static bool operator >(JET_LGPOS lhs, JET_LGPOS rhs)
        {
            return lhs.CompareTo(rhs) > 0;
        }
        /// 
        /// Determine whether one log position is before or equal to
        /// another log position.
        /// 
        /// The first log position to compare.
        /// The second log position to compare.
        /// True if lhs comes before or is equal to rhs.
        public static bool operator <=(JET_LGPOS lhs, JET_LGPOS rhs)
        {
            return lhs.CompareTo(rhs) <= 0;
        }
        /// 
        /// Determine whether one log position is after or equal to
        /// another log position.
        /// 
        /// The first log position to compare.
        /// The second log position to compare.
        /// True if lhs comes after or is equal to rhs.
        public static bool operator >=(JET_LGPOS lhs, JET_LGPOS rhs)
        {
            return lhs.CompareTo(rhs) >= 0;
        }
        /// 
        /// Generate a string representation of the structure.
        /// 
        /// The structure as a string.
        public override string ToString()
        {
            return string.Format(
                CultureInfo.InvariantCulture,
                "JET_LGPOS(0x{0:X},{1:X},{2:X})",
                this.lGeneration,
                this.isec,
                this.ib);
        }
        /// 
        /// Returns a value indicating whether this instance is equal
        /// to another instance.
        /// 
        /// An object to compare with this instance.
        /// True if the two instances are equal.
        public override bool Equals(object obj)
        {
            if (obj == null || this.GetType() != obj.GetType())
            {
                return false;
            }
            return this.Equals((JET_LGPOS)obj);
        }
        /// 
        /// Returns the hash code for this instance.
        /// 
        /// The hash code for this instance.
        public override int GetHashCode()
        {
            return this.generation ^ (this.sector << 16) ^ this.offset;
        }
        /// 
        /// Returns a value indicating whether this instance is equal
        /// to another instance.
        /// 
        /// An instance to compare with this instance.
        /// True if the two instances are equal.
        public bool Equals(JET_LGPOS other)
        {
            return this.generation == other.generation
                   && this.sector == other.sector
                   && this.offset == other.offset;
        }
        /// 
        /// Compares this log position to another log position and determines
        /// whether this instance is before, the same as or after the other
        /// instance.
        /// 
        /// The log position to compare to the current instance.
        /// 
        /// A signed number indicating the relative positions of this instance and the value parameter.
        /// 
        public int CompareTo(JET_LGPOS other)
        {
            int compare = this.generation.CompareTo(other.generation);
            if (0 == compare)
            {
                compare = this.sector.CompareTo(other.sector);
            }
            if (0 == compare)
            {
                compare = this.offset.CompareTo(other.offset);
            }
            return compare;
        }
    }
}