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

namespace skyscraper5.src.InteractionChannel.Model
{
	public class Tbtp : Validatable
	{
		public const bool EIGHT_BIT_CHANNEL_ID = true;

		public Tbtp(MemoryStream ms)
		{
			InBitStream ibs = new InBitStream(ms);
			GroupId = ibs.ReadBitsAsUint(8);
			SuperframeCount = ibs.ReadBitsAsUint(16);

			uint reserved = ibs.ReadBitsAsUint(3);
			uint frameLoopCount = ibs.ReadBitsAsUint(5); frameLoopCount++;
			Frames = new TbtpFrame[frameLoopCount];
			for (uint i = 0; i < frameLoopCount; i++)
			{
				uint reserved2 = ibs.ReadBitsAsUint(3);
				Frames[i] = new TbtpFrame();
				Frames[i].FrameNumber = ibs.ReadBitsAsUint(5);
				uint reserved3 = ibs.ReadBitsAsUint(5);
				uint btpLoopCount = ibs.ReadBitsAsUint(11); btpLoopCount++;
				Frames[i].BTP = new TbtpFrame.BtpEntity[btpLoopCount];
				for (uint j = 0; j < btpLoopCount; j++)
				{
					Frames[i].BTP[j] = new TbtpFrame.BtpEntity();
					Frames[i].BTP[j].LogonId = ibs.ReadBitsAsUint(16);
					bool multipleChannelsFlag = ibs.ReadBitAsBoolean();
					Frames[i].BTP[j].AssignmentType = (TbtpFrame.BtpEntity.AssignType)ibs.ReadBitsAsUint(2);
					Frames[i].BTP[j].VbdcQueueEmptyFlag = ibs.ReadBitAsBoolean();
					bool reserved4 = ibs.ReadBitAsBoolean();
					Frames[i].BTP[j].StartSlot = ibs.ReadBitsAsUint(11);
					if (multipleChannelsFlag)
					{
						Frames[i].BTP[j].ChannelId = ibs.ReadBitsAsUint(8);
					}
					Frames[i].BTP[j].AssignmentCount = ibs.ReadBitsAsUint(8);
				}
			}
			uint crc32 = ibs.ReadBitsAsUint(32);
			Valid = true;
		}

		public uint GroupId { get; }
		public uint SuperframeCount { get; }
		public TbtpFrame[] Frames { get; }

		public class TbtpFrame
		{
			public uint FrameNumber { get; internal set; }
			public BtpEntity[] BTP { get; internal set; }

			public class BtpEntity
			{
				public uint LogonId { get; internal set; }
				public AssignType AssignmentType { get; internal set; }
				public bool VbdcQueueEmptyFlag { get; internal set; }
				public uint StartSlot { get; internal set; }
				public uint? ChannelId { get; internal set; }
				public uint AssignmentCount { get; internal set; }

				public enum AssignType
				{
					OneTimeAssignment = 0,
					RepeatingAssignment = 1,
					AssignmentRelease = 2
				}
			}
		}
	}
}
