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.Model2
{
	public class Tbtp2 : Validatable
	{
		public Tbtp2(MemoryStream ms)
		{
			GroupId = ms.ReadUInt8();
			SuperframeSequence = ms.ReadUInt8();
			AssignmentContext = ms.ReadUInt8();
			SuperframeCount = ms.ReadUInt8();
			AssignmentFormat = ms.ReadUInt8();

			byte frameLoopCount = ms.ReadUInt8();
			frameLoopCount++;
			Frames = new Frame[frameLoopCount];
			for (int i = 0; i < Frames.Length; i++)
			{
				Frames[i] = new Frame();
				Frames[i].FrameNumber = ms.ReadUInt8();
				Frames[i].AssignmentOffset = ms.ReadUInt16BE();
				ushort assignmentLoopCount = ms.ReadUInt16BE();
				assignmentLoopCount++;
				long sizeRequired = assignmentLoopCount * GetFormatSize();
				if (ms.GetAvailableBytes() < sizeRequired)
				{
					Valid = false;
					return;
				}
				Frames[i].Assignments = new Assignment[assignmentLoopCount];
				for (int j = 0; j < assignmentLoopCount; j++)
				{
					Frames[i].Assignments[j] = new Assignment();
					if (AssignmentFormat == 0)
					{
						Frames[i].Assignments[j].AssignmentId = ms.ReadBytes(6);
					}
					if (AssignmentFormat == 1)
					{
						Frames[i].Assignments[j].AssignmentId = ms.ReadBytes(1);
					}
					if (AssignmentFormat == 2)
					{
						Frames[i].Assignments[j].AssignmentId = ms.ReadBytes(2);
					}
					if (AssignmentFormat == 3)
					{
						Frames[i].Assignments[j].AssignmentId = ms.ReadBytes(3);
					}
					if (AssignmentFormat == 10)
					{
						Frames[i].Assignments[j].DynamicTxType = ms.ReadUInt8();
						Frames[i].Assignments[j].AssignmentId = ms.ReadBytes(1);
					}
					if (AssignmentFormat == 11)
					{
						Frames[i].Assignments[j].DynamicTxType = ms.ReadUInt8();
						Frames[i].Assignments[j].AssignmentId = ms.ReadBytes(2);
					}
					if (AssignmentFormat == 12)
					{
						Frames[i].Assignments[j].DynamicTxType = ms.ReadUInt8();
						Frames[i].Assignments[j].AssignmentId = ms.ReadBytes(3);
					}
					if (AssignmentFormat > 127)
					{
						CannotParse = true;
						return;
					}
				}
			}

			long remainingContent = ms.GetAvailableBytes();
			remainingContent -= 4;
			if (remainingContent > 0)
			{
				long reservedPerUnit = remainingContent;
				reservedPerUnit -= frameLoopCount;
				reservedPerUnit /= frameLoopCount;
			}

			Valid = true;
			CannotParse = false;
		}

		public byte GroupId { get; }
		public byte SuperframeSequence { get; }
		public byte AssignmentContext { get; }
		public byte SuperframeCount { get; }
		public byte AssignmentFormat { get; }
		public Frame[] Frames { get; }

		public class Frame
		{
			public byte FrameNumber { get; internal set; }
			public ushort AssignmentOffset { get; internal set; }
			public Assignment[] Assignments { get; internal set; }
		}

		public class Assignment
		{
			public byte[] AssignmentId { get; internal set; }
			public byte? DynamicTxType { get; internal set; }
		}

		public bool? CannotParse { get; }

		public int GetFormatSize()
		{
			switch(AssignmentFormat)
			{
				case 0: return 6;
				case 1: return 1;
				case 2: return 2;
				case 3: return 3;
				case 10: return 2;
				case 11: return 3;
				case 12: return 4;
				default:
					if (AssignmentFormat > 127)
					{
						Valid = false;
						return 100;
					}
					return 0;
			}
		}
	}
}
