using System;

namespace skyscraper5.Mpeg2
{
    public class PcrMonitor
    {
        internal PcrMonitor(TsPacket packet)
        {
            Analyze(packet);
        }

        internal void Analyze(TsPacket packet)
        {
            if (packet.AdaptionField == null)
                return;
            if (!packet.AdaptionField.Valid)
                return;
            if (!packet.AdaptionField.PcrPresent)
                return;

            if (StartPcr == null)
            {
                StartPcr = packet.AdaptionField.PCR;
                SourcePid = packet.PID;
                StartRealTime = DateTime.Now;
            }
            else
            {
                if (packet.PID == SourcePid)
                {
                    LastPcr = packet.AdaptionField.PCR;
                    LastRealTime = DateTime.Now;
                }
            }
        }

        public uint SourcePid { get; private set; }

        public ulong? LastPcr { get; private set; }

        public ulong? StartPcr { get; private set; }

        public DateTime StartRealTime { get; private set; }
        public DateTime? LastRealTime { get; private set; }

        public TimeSpan StartPcrTimeStamp
        {
            get
            {
                ulong seconds = StartPcr.Value / 27000000;
                ulong ticks = seconds * TimeSpan.TicksPerSecond;
                return new TimeSpan((long)ticks);
            }
        }

        public TimeSpan? EndPcrTimeStamp
        {
            get
            {
                if (LastPcr == null)
                    return null;

                ulong seconds = LastPcr.Value / 27000000;
                ulong ticks = seconds * TimeSpan.TicksPerSecond;
                return new TimeSpan((long)ticks);
            }
        }

        public TimeSpan? PcrDuration
        {
            get
            {
                if (EndPcrTimeStamp == null)
                    return null;

                return new TimeSpan(EndPcrTimeStamp.Value.Ticks - StartPcrTimeStamp.Ticks);
            }
        }

        public TimeSpan? RealTimeDuration
        {
            get
            {
                if (LastRealTime == null)
                    return null;

                return LastRealTime.Value - StartRealTime;
            }
        }

        public double? Performance
        {
            get
            {
                if (!PcrDuration.HasValue)
                    return null;
                if (!RealTimeDuration.HasValue)
                    return null;

                double pcr = PcrDuration.Value.TotalSeconds;
                double real = RealTimeDuration.Value.TotalSeconds;
                double result = pcr / real;
                return Math.Round(result, 1);
            }
        }
    }
}
