// 
// Copyright (c) 2013-2016 Carsten Sonne Larsen <cs@innolan.dk>
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

namespace Ntp.Analyzer.Objects
{
    public sealed class AssociationEntry : PersistentObject
    {
        public AssociationEntry(
            int id, int hostId, char tallyChar,
            string remote, string refid, int stratus, char peerType,
            int lastPoll, int poll, int reach,
            double delay, double offset, double jitter)
            : base(id)
        {
            HostId = hostId;
            TallyChar = tallyChar;
            Remote = remote;
            this.refid = refid;
            Stratus = stratus;
            PeerType = peerType;
            LastPoll = lastPoll;
            Poll = poll;
            Reach = reach;
            Delay = delay;
            Offset = offset;
            Jitter = jitter;
        }

        public AssociationEntry(
            int hostId, char tallyChar,
            string remote, string refid, int stratus, char peerType,
            int lastPoll, int poll, int reach,
            double delay, double offset, double jitter)
        {
            HostId = hostId;
            TallyChar = tallyChar;
            Remote = remote;
            this.refid = refid;
            Stratus = stratus;
            PeerType = peerType;
            LastPoll = lastPoll;
            Poll = poll;
            Reach = reach;
            Delay = delay;
            Offset = offset;
            Jitter = jitter;
        }

        private readonly string refid;

        /// <summary>
        /// Gets the tally code.
        /// </summary>
        /// <value>The tally code. </value>
        public TallyCode TallyCode
        {
            get
            {
                switch (TallyChar)
                {
                    case ' ':
                        return TallyCode.Reject;
                    case 'x':
                        return TallyCode.FalseTick;
                    case '.':
                        return TallyCode.Excess;
                    case '-':
                        return TallyCode.Outlyer;
                    case '+':
                        return TallyCode.Candidat;
                    case '#':
                        return TallyCode.Selected;
                    case '*':
                        return TallyCode.SysPeer;
                    case 'o':
                        return TallyCode.PpsPeer;
                    default:
                        return TallyCode.Undefined;
                }
            }
        }

        /// <summary>
        /// Gets the tally char.
        /// </summary>
        /// <value>The tally char.</value>
        public char TallyChar { get; }

        /// <summary>
        /// Gets the host ID of this association entry.
        /// </summary>
        /// <value>The host ID.</value>
        public int HostId { get; }

        /// <summary>
        /// Gets the address of the remote peer.
        /// </summary>
        /// <value>The address.</value>
        public string Remote { get; }

        /// <summary>
        /// Gets the reference ID (0.0.0.0 if this is unknown)
        /// </summary>
        /// <value>The reference ID.</value>
        public string Refid => refid ?? "0.0.0.0";

        /// <summary>
        /// Gets the stratum of the remote peer.
        /// </summary>
        /// <value>The stratus.</value>
        public int Stratus { get; }

        /// <summary>
        /// Gets the type of the peer (local, unicast, multicast or broadcast)
        /// </summary>
        /// <value>l, u, m or b</value>
        public char PeerType { get; }

        /// <summary>
        /// Gets when the last packet was received, the polling interval, in seconds.
        /// </summary>
        /// <value>The last poll in seconds.</value>
        public int LastPoll { get; }

        /// <summary>
        /// Gets the the polling interval in seconds.
        /// </summary>
        /// <value>The polling interval.</value>
        public int Poll { get; }

        /// <summary>
        /// Gets the reachability register in octal.
        /// </summary>
        /// <value>The reachability register.</value>
        public int Reach { get; }

        /// <summary>
        /// Gets the current estimated delay.
        /// </summary>
        /// <value>The estimated delay.</value>
        public double Delay { get; }

        /// <summary>
        /// Gets the offset of the peer in milliseconds.
        /// </summary>
        /// <value>The offset.</value>
        public double Offset { get; }

        /// <summary>
        /// Gets the dispersion of the peer in milliseconds.
        /// </summary>
        /// <value>The dispersion.</value>
        public double Jitter { get; }
    }
}