using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace skyscraper5.src.InteractionChannel.Model.Descriptors
{
	[SkyscraperPlugin]
	[TsDescriptor(0xad,"TIM")]
	public class _0xad_ForwardInteractionPathDescriptor : TsDescriptor
	{
		public _0xad_ForwardInteractionPathDescriptor(byte[] buffer)
		{
			MemoryStream ms = new MemoryStream(buffer, false);
			while (ms.GetAvailableBytes() >= 5)
			{
				if (Paths == null)
					Paths = new List<ForwardInteractionPath>();

				ForwardInteractionPath child = new ForwardInteractionPath();
				child.OriginalNetworkId = ms.ReadUInt16BE();
				child.TransportStreamId = ms.ReadUInt16BE();
				int pidLoopCount = ms.ReadUInt8() & 0x0f;
				
				int sizeRequired = pidLoopCount * 2;
				if (ms.GetAvailableBytes() < sizeRequired)
				{
					Valid = false;
					return;
				}
				child.Pids = new ushort[pidLoopCount];
				for (int i = 0; i < pidLoopCount; i++)
				{
					child.Pids[i] = ms.ReadUInt16BE();
				}
				Paths.Add(child);
			}
			Valid = true;
		}

		public class ForwardInteractionPath
		{
			public ushort OriginalNetworkId { get; internal set; }
			public ushort TransportStreamId { get; internal set; }
			public ushort[] Pids { get; internal set; }

			public string PidsAsString
			{
				get
				{
					StringBuilder sb = new StringBuilder();
					foreach (var p in Pids)
					{
						sb.Append(p);
						sb.Append(";");
					}

					return sb.ToString();
				}
			}

			protected bool Equals(ForwardInteractionPath other)
			{
				return PidsAsString.Equals(other.PidsAsString) && OriginalNetworkId == other.OriginalNetworkId && TransportStreamId == other.TransportStreamId;
			}

			public override bool Equals(object? obj)
			{
				if (ReferenceEquals(null, obj)) return false;
				if (ReferenceEquals(this, obj)) return true;
				if (obj.GetType() != this.GetType()) return false;
				return Equals((ForwardInteractionPath)obj);
			}

			public override int GetHashCode()
			{
				return HashCode.Combine(OriginalNetworkId, TransportStreamId);
			}

			public override string ToString()
			{
				bool suspect = false;
				StringBuilder sb = new StringBuilder();
				sb.AppendFormat("ONID: {0}, TSID: {1}, PIDs: ", OriginalNetworkId, TransportStreamId);
				foreach (var p in Pids)
				{
					sb.Append(p);
					sb.Append(";");
					if (p > 8192)
						suspect = true;
				}

				if (suspect)
				{
					sb.AppendFormat(" (suspected GS)");
				}
				return sb.ToString();
			}
		}

		public List<ForwardInteractionPath> Paths { get; }

		public override string ToString()
		{
			return String.Format("{0} Forward Interaction Paths", Paths.Count);
		}
	}
}
