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(0xae,"TIM")]
	internal class _0xae_ReturnInteractionPathDescriptor : TsDescriptor
	{
		public _0xae_ReturnInteractionPathDescriptor(byte[] buffer)
		{
			MemoryStream ms = new MemoryStream(buffer, false);
			byte bytea = ms.ReadUInt8();
			ContinuousCarrier = (bytea & 0x10) != 0;

			int networkRoutingLabelLoopCount = (bytea & 0x0f);
			networkRoutingLabelLoopCount++;
			RoutingLabels = new RoutingLabel[networkRoutingLabelLoopCount];
			for (int i = 0; i < networkRoutingLabelLoopCount; i++)
			{
				RoutingLabels[i] = new RoutingLabel();
				byte byteb = ms.ReadUInt8();
				RoutingLabels[i].AllocationDesallocationFlag = (byteb & 0x02) != 0;
				bool pidFlag = (byteb & 0x01) != 0;
				if (pidFlag)
				{
					byte pidLoopCount = ms.ReadUInt8();
					pidLoopCount++;
					int bytesRequired = pidLoopCount * 2;
					if (ms.GetAvailableBytes() < bytesRequired)
					{
						Valid = false;
						return;
					}

					RoutingLabels[i].PIDs = new ushort[pidLoopCount];
					for (int j = 0; j < pidLoopCount; j++)
					{
						RoutingLabels[i].PIDs[j] = ms.ReadUInt16BE();
					}
				}

				byte bytec = ms.ReadUInt8();
				bool vpiVciFlag = (bytec & 0x01) != 0;
				if (vpiVciFlag)
				{
					byte vpiVciCount = ms.ReadUInt8();
					vpiVciCount++;
					int bytesRequired = vpiVciCount * 2;
					if (ms.GetAvailableBytes() < bytesRequired)
					{
						Valid = false;
						return;
					}

					RoutingLabels[i].VpiVciPairs = new VpiVciPair[vpiVciCount];
					for (int k = 0; k < vpiVciCount; k++)
					{
						RoutingLabels[i].VpiVciPairs[k] = new VpiVciPair();
						RoutingLabels[i].VpiVciPairs[k].VPI = ms.ReadUInt8();
						RoutingLabels[i].VpiVciPairs[k].VCI = ms.ReadUInt16BE();
					}
				}

				byte byted = ms.ReadUInt8();
				bool routeIdFlag = (byted & 0x01) != 0;
				if (routeIdFlag)
				{
					byte routeIdCount = ms.ReadUInt8();
					routeIdCount++;
					int bytesRequired = routeIdCount * 2;
					if (ms.GetAvailableBytes() < bytesRequired)
					{
						Valid = false;
						return;
					}

					RoutingLabels[i].RouteIds = new ushort[routeIdCount];
					for (int l = 0; l < routeIdCount; l++)
					{
						RoutingLabels[i].RouteIds[l] = ms.ReadUInt16LE();
					}
				}

				ChannelId = ms.ReadUInt8() & 0x0f;
			}
		}

		public bool ContinuousCarrier { get; }
		public RoutingLabel[] RoutingLabels { get; }
		public int ChannelId { get; }

		public class RoutingLabel
		{
			public bool AllocationDesallocationFlag { get; internal set; }
			public ushort[] PIDs { get; internal set; }
			public VpiVciPair[] VpiVciPairs { get; internal set; }
			public ushort[] RouteIds { get; internal set; }
		}

		public class VpiVciPair
		{
			public byte VPI { get; internal set; }
			public ushort VCI { get; internal set; }
		}

		public override string ToString()
		{
			return String.Format("{0} Return Interaction Paths", RoutingLabels.Length);
		}
	}
}
