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 Fct : Validatable
	{
		public Fct(MemoryStream ms) 
		{
			byte frameIdLoopCount = ms.ReadUInt8(); frameIdLoopCount++;
			Frames = new Frame[frameIdLoopCount];
			for (int i = 0; i < frameIdLoopCount; i++)
			{
				if (ms.GetAvailableBytes() < 10)
				{
					Valid = false;
					return;
				}
				Frames[i] = new Frame();
				Frames[i].FrameId = ms.ReadUInt8();
				Frames[i].FrameDuration = ms.ReadUInt32BE();
				Frames[i].TotalTimeslotCount = ms.ReadUInt16BE() & 0x07ff;
				Frames[i].StartTimeslotNumber = ms.ReadUInt16BE() & 0x07ff;
				byte timeslotLoopCount = ms.ReadUInt8(); timeslotLoopCount++;
				Frames[i].Timeslots = new Frame.Timeslot[timeslotLoopCount];
				for (int j = 0; j <  timeslotLoopCount; j++)
				{
					if (ms.GetAvailableBytes() < 9)
					{
						Valid = false;
						return;
					}
					Frames[i].Timeslots[j] = new Frame.Timeslot();
					Frames[i].Timeslots[j].TimeslotFrequencyOffset = ms.ReadUInt24BE();
					Frames[i].Timeslots[j].TimeslotTimeOffset = ms.ReadUInt32BE();
					Frames[i].Timeslots[j].TimeslotId = ms.ReadUInt8();
					Frames[i].Timeslots[j].RepeatCount = ms.ReadUInt8();
				}
			}
			uint crc32 = ms.ReadUInt32BE();
			Valid = true;
		}

		public class Frame
		{
			public byte FrameId { get; internal set; }
			public uint FrameDuration { get; internal set; }
			public int TotalTimeslotCount { get; internal set; }
			public int StartTimeslotNumber { get; internal set; }
			public Timeslot[] Timeslots { get; internal set; }

			public class Timeslot
			{
				public uint TimeslotFrequencyOffset { get; internal set; }
				public uint TimeslotTimeOffset { get; internal set; }
				public byte TimeslotId { get; internal set; }
				public byte RepeatCount { get; internal set; }
			}

			protected bool Equals(Frame other)
			{
				return FrameId == other.FrameId && FrameDuration == other.FrameDuration && TotalTimeslotCount == other.TotalTimeslotCount && StartTimeslotNumber == other.StartTimeslotNumber;
			}

			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((Frame)obj);
			}

			public override int GetHashCode()
			{
				return HashCode.Combine(FrameId, FrameDuration, TotalTimeslotCount, StartTimeslotNumber);
			}
		}

		public Frame[] Frames { get; }
	}
}
